From e7002712a5aeda01638932d1001a2926a96b9332 Mon Sep 17 00:00:00 2001 From: dsantosferreira Date: Sat, 14 Jan 2023 20:28:15 +0000 Subject: [PATCH 01/30] Added time interval to add second application with the same email address Co-authored-by: Francisco Cardoso --- .../validators/validationReasons.js | 1 + src/api/routes/application.js | 27 +++++++++++++++++++ src/models/Account.js | 1 + src/models/CompanyApplication.js | 9 +++++-- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/api/middleware/validators/validationReasons.js b/src/api/middleware/validators/validationReasons.js index 7a38a793..8ab305e1 100644 --- a/src/api/middleware/validators/validationReasons.js +++ b/src/api/middleware/validators/validationReasons.js @@ -50,6 +50,7 @@ const ValidationReasons = Object.freeze({ OFFER_HIDDEN: "offer-is-hidden", FILE_TOO_LARGE: (max) => `file-cant-be-larger-than-${max}MB`, MUST_BE_GREATER_THAN_OR_EQUAL_TO: (field) => `must-be-greater-than-or-equal-to:${field}`, + APPLICATION_RECENTLY_CREATED: "application-created-in-less-than-five-minutes-ago", }); export default ValidationReasons; diff --git a/src/api/routes/application.js b/src/api/routes/application.js index d129b452..abdf12de 100644 --- a/src/api/routes/application.js +++ b/src/api/routes/application.js @@ -1,7 +1,11 @@ import { Router } from "express"; +import { StatusCodes as HTTPStatus } from "http-status-codes"; import * as validators from "../middleware/validators/application.js"; import ApplicationService from "../../services/application.js"; +import CompanyApplication from "../../models/CompanyApplication.js"; +import { ErrorTypes, APIError } from "../middleware/errorHandler.js"; +import ValidationReasons from "../middleware/validators/validationReasons.js"; const router = Router(); @@ -12,7 +16,29 @@ export default (app) => { * Creates a new Company Application */ router.post("/", validators.create, async (req, res, next) => { + /* + When creating a new Company Application verifies if there is already a application pending with the same email of the + new apllication, if so verifies if the already existing application was created at at least 5 minutes if so then the old + application is deleted, otherwise an error is return indication that there is already an application from that company + */ + const cursor = await CompanyApplication.findOne({ email: req.body.email, isVerified: false }).exec(); + if (cursor !== null) { + if (Date.now() - cursor.submittedAt < 5000 * 60) { + return next(new APIError( + HTTPStatus.FORBIDDEN, + ErrorTypes.FORBIDDEN, + ValidationReasons.APPLICATION_RECENTLY_CREATED)); + } else { + await CompanyApplication.deleteMany({ email: req.body.email, isVerified: false }).then(function() { + console.log("Data deleted"); // Success + }).catch(function(error) { + console.error(error); + return next(error); // Failure + }); + } + } + // Creates a new application try { // This is safe since the service is destructuring the passed object and the fields have been validated const application = await (new ApplicationService()).create(req.body); @@ -22,4 +48,5 @@ export default (app) => { return next(err); } }); + }; diff --git a/src/models/Account.js b/src/models/Account.js index 2430a4e7..b3dd067d 100644 --- a/src/models/Account.js +++ b/src/models/Account.js @@ -35,6 +35,7 @@ const AccountSchema = new Schema({ }, }, + }); AccountSchema.methods.validatePassword = async function(password) { diff --git a/src/models/CompanyApplication.js b/src/models/CompanyApplication.js index 766f8962..8c6fb9fb 100644 --- a/src/models/CompanyApplication.js +++ b/src/models/CompanyApplication.js @@ -80,6 +80,10 @@ export const CompanyApplicationProps = { return !!this.rejectedAt; }, }, + isVerified: { + type: Boolean, + default: false, + }, }; const CompanyApplicationSchema = new Schema(CompanyApplicationProps); @@ -116,8 +120,9 @@ function validateMutuallyExclusiveEvents(field) { export const applicationUniqueness = async (email) => { const existingApplications = await CompanyApplication.find({ email }); if (existingApplications.some((application) => - application.state === ApplicationStatus.PENDING || - application.state === ApplicationStatus.APPROVED) + (application.state === ApplicationStatus.PENDING || + application.state === ApplicationStatus.APPROVED) && + application.isVerified) ) { throw new Error(CompanyApplicationRules.ONLY_ONE_APPLICATION_ACTIVE_PER_EMAIL.msg); } From e3ba9c7b56c03d7ade46c965ccf57c21f1bed7af Mon Sep 17 00:00:00 2001 From: dsantosferreira Date: Sat, 14 Jan 2023 21:51:56 +0000 Subject: [PATCH 02/30] Moved time interval logic to validator Co-authored-by: Francisco Cardoso --- src/api/middleware/validators/application.js | 3 +- src/api/routes/application.js | 35 +++++--------------- src/models/CompanyApplication.js | 21 ++++++++++++ 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/api/middleware/validators/application.js b/src/api/middleware/validators/application.js index 59cd85c9..ed8ec1df 100644 --- a/src/api/middleware/validators/application.js +++ b/src/api/middleware/validators/application.js @@ -6,7 +6,7 @@ import ValidationReasons from "./validationReasons.js"; import { checkDuplicatedEmail, valuesInSet, ensureArray } from "./validatorUtils.js"; import CompanyApplicationConstants from "../../../models/constants/CompanyApplication.js"; import CompanyConstants from "../../../models/constants/Company.js"; -import { applicationUniqueness, CompanyApplicationProps } from "../../../models/CompanyApplication.js"; +import { applicationUniqueness, exceededCreationTimeLimit, CompanyApplicationProps } from "../../../models/CompanyApplication.js"; import ApplicationStatus from "../../../models/constants/ApplicationStatus.js"; import { password } from "./auth.js"; @@ -19,6 +19,7 @@ export const create = useExpressValidators([ .bail() .custom(checkDuplicatedEmail).bail() .custom(applicationUniqueness) + .custom(exceededCreationTimeLimit) .trim(), password, diff --git a/src/api/routes/application.js b/src/api/routes/application.js index abdf12de..e7514319 100644 --- a/src/api/routes/application.js +++ b/src/api/routes/application.js @@ -1,11 +1,8 @@ import { Router } from "express"; - -import { StatusCodes as HTTPStatus } from "http-status-codes"; import * as validators from "../middleware/validators/application.js"; import ApplicationService from "../../services/application.js"; import CompanyApplication from "../../models/CompanyApplication.js"; -import { ErrorTypes, APIError } from "../middleware/errorHandler.js"; -import ValidationReasons from "../middleware/validators/validationReasons.js"; + const router = Router(); @@ -16,29 +13,13 @@ export default (app) => { * Creates a new Company Application */ router.post("/", validators.create, async (req, res, next) => { - /* - When creating a new Company Application verifies if there is already a application pending with the same email of the - new apllication, if so verifies if the already existing application was created at at least 5 minutes if so then the old - application is deleted, otherwise an error is return indication that there is already an application from that company - */ - - const cursor = await CompanyApplication.findOne({ email: req.body.email, isVerified: false }).exec(); - if (cursor !== null) { - if (Date.now() - cursor.submittedAt < 5000 * 60) { - return next(new APIError( - HTTPStatus.FORBIDDEN, - ErrorTypes.FORBIDDEN, - ValidationReasons.APPLICATION_RECENTLY_CREATED)); - } else { - await CompanyApplication.deleteMany({ email: req.body.email, isVerified: false }).then(function() { - console.log("Data deleted"); // Success - }).catch(function(error) { - console.error(error); - return next(error); // Failure - }); - } - } - // Creates a new application + + await CompanyApplication.deleteMany({ email: req.body.email, isVerified: false }).catch(function(error) { + console.error(error); + return next(error); // Failure + }); + + try { // This is safe since the service is destructuring the passed object and the fields have been validated const application = await (new ApplicationService()).create(req.body); diff --git a/src/models/CompanyApplication.js b/src/models/CompanyApplication.js index 8c6fb9fb..01af0236 100644 --- a/src/models/CompanyApplication.js +++ b/src/models/CompanyApplication.js @@ -33,6 +33,10 @@ export const CompanyApplicationRules = Object.freeze({ CANNOT_REVIEW_TWICE: { msg: "company-application-already-reviewed", }, + APPLICATION_RECENTLY_CREATED: { + validator: validateExceededCreationTimeLimit, + msg: "application-created-in-less-than-five-minutes-ago" + } }); export const CompanyApplicationProps = { @@ -130,6 +134,23 @@ export const applicationUniqueness = async (email) => { return true; }; +export const exceededCreationTimeLimit = async (email) => { + const cursor = await CompanyApplication.findOne({ email, isVerified: false }).exec(); + if (cursor !== null && Date.now() - cursor.submittedAt < 5000 * 60) { + throw new Error(CompanyApplicationRules.APPLICATION_RECENTLY_CREATED.msg); + } + return true; +}; + +async function validateExceededCreationTimeLimit(value) { + try { + await applicationUniqueness(value); + } catch (e) { + return false; + } + return true; +} + async function validateSingleActiveApplication(value) { try { await applicationUniqueness(value); From ba84863cbc494141a84b0b477f82eb8758c89b83 Mon Sep 17 00:00:00 2001 From: dsantosferreira Date: Tue, 24 Jan 2023 16:47:08 +0000 Subject: [PATCH 03/30] Sends an email to company to confirm application (not tested) Co-authored-by: Francisco Cardoso --- .env | 5 ++++- src/api/routes/application.js | 5 ++++- src/config/env.js | 1 + .../companyApplicationConfirmation.js | 5 +++++ .../confirm-application.handlebars | 6 ++++++ src/models/constants/ApplicationStatus.js | 2 ++ src/services/application.js | 20 +++++++++++++++++++ 7 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 src/email-templates/companyApplicationConfirmation.js create mode 100644 src/email-templates/confirm-application.handlebars diff --git a/.env b/.env index 0bdfbe73..9f7f72ce 100644 --- a/.env +++ b/.env @@ -20,6 +20,9 @@ JWT_SECRET=Lendas contam que o Rui foi membro do IEEE. # Frontend Password Recovery Base Route PASSWORD_RECOVERY_LINK=https://localhost:3000/recover +# Froantend Application Confirmation Base Route +APPLICATION_CONFIRMATION_LINK=https://villate.org/eletricidade/fluxo.html + # Specifies the port in which the app will be exposed PORT=8087 @@ -45,7 +48,7 @@ ACCESS_CONTROL_ALLOW_ORIGINS= MAIL_FROM= # Password for email above -MAIL_FROM_PASSWORD= +MAIL_FROM_PASSWORD= # Cloudinary API URL to save images CLOUDINARY_URL= diff --git a/src/api/routes/application.js b/src/api/routes/application.js index e7514319..db15c004 100644 --- a/src/api/routes/application.js +++ b/src/api/routes/application.js @@ -21,8 +21,11 @@ export default (app) => { try { + const applicationService = new ApplicationService(); // This is safe since the service is destructuring the passed object and the fields have been validated - const application = await (new ApplicationService()).create(req.body); + const application = await applicationService.create(req.body); + const link = applicationService.buildConfirmationLink(application._id); // ObjectId(application) + applicationService.sendConfirmationNotification(application.email, link); return res.json(application); } catch (err) { console.error(err); diff --git a/src/config/env.js b/src/config/env.js index b910e901..78a36ffa 100644 --- a/src/config/env.js +++ b/src/config/env.js @@ -23,6 +23,7 @@ export default Object.freeze({ session_secret: process.env.SESSION_SECRET, jwt_secret: process.env.JWT_SECRET, password_recovery_link: process.env.PASSWORD_RECOVERY_LINK, + application_confirmation_link: process.env.APPLICATION_CONFIRMATION_LINK, port: process.env.PORT, god_token: process.env.GOD_TOKEN, test_log_requests: JSON.parse(process.env.TEST_LOG_REQUESTS), diff --git a/src/email-templates/companyApplicationConfirmation.js b/src/email-templates/companyApplicationConfirmation.js new file mode 100644 index 00000000..d1ce9d02 --- /dev/null +++ b/src/email-templates/companyApplicationConfirmation.js @@ -0,0 +1,5 @@ +export const APPLICATION_CONFIRMATION = (link) => ({ + subject: "Confirm your NIJobs application", + template: "request_password_recovery", + context: { link }, +}); diff --git a/src/email-templates/confirm-application.handlebars b/src/email-templates/confirm-application.handlebars new file mode 100644 index 00000000..aceaa777 --- /dev/null +++ b/src/email-templates/confirm-application.handlebars @@ -0,0 +1,6 @@ +

Confirm your NIJobs application

+

Please follow this link to finish the process. Note that the link will be expired in 5 minutes.

+
+

If you did not request this or need anything else, please contact us at nijobs@aefeup.pt!


+

Sincerely,

+

NIJobs team at NIAEFEUP

\ No newline at end of file diff --git a/src/models/constants/ApplicationStatus.js b/src/models/constants/ApplicationStatus.js index a6f504ca..eb2bcca2 100644 --- a/src/models/constants/ApplicationStatus.js +++ b/src/models/constants/ApplicationStatus.js @@ -5,3 +5,5 @@ const ApplicationStatus = Object.freeze({ }); export default ApplicationStatus; + +export const RECOVERY_LINK_EXPIRATION = 300; diff --git a/src/services/application.js b/src/services/application.js index abc0bc8c..3012cc40 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -1,5 +1,8 @@ import CompanyApplication, { CompanyApplicationRules } from "../models/CompanyApplication.js"; +import { generateToken } from "../lib/token.js"; import hash from "../lib/passwordHashing.js"; +import { RECOVERY_LINK_EXPIRATION } from "../models/constants/ApplicationStatus.js"; +import { APPLICATION_CONFIRMATION } from "../email-templates/companyApplicationConfirmation.js"; import AccountService from "./account.js"; import EmailService from "../lib/emailService.js"; import { @@ -216,6 +219,23 @@ class CompanyApplicationService { throw new CompanyApplicationAlreadyReviewed(CompanyApplicationRules.CANNOT_REVIEW_TWICE.msg); } } + + buildConfirmationLink(id) { + const token = generateToken({ _id: id }, config.jwt_secret, RECOVERY_LINK_EXPIRATION); + return `${config.application_confirmation_link}/${token}`; + } + + async sendConfirmationNotification(email, link) { + try { + await EmailService.sendMail({ + to: email, + ...APPLICATION_CONFIRMATION(link), + }); + } catch (err) { + console.error(err); + throw err; + } + } } export default CompanyApplicationService; From 3fd941b0fb19fc42818aae3f2f2ba98da81fe160 Mon Sep 17 00:00:00 2001 From: Francisco Cardoso Date: Thu, 26 Jan 2023 10:03:37 +0000 Subject: [PATCH 04/30] Changing validators to middleware and creating routes to validate applications Co-authored-by: Daniel Ferreira --- src/api/middleware/application.js | 16 +++++++++++ src/api/middleware/validators/application.js | 3 +- src/api/routes/application.js | 28 +++++++++++++------ .../companyApplicationConfirmation.js | 2 +- src/models/CompanyApplication.js | 28 ++++++------------- src/services/application.js | 4 +++ 6 files changed, 49 insertions(+), 32 deletions(-) create mode 100644 src/api/middleware/application.js diff --git a/src/api/middleware/application.js b/src/api/middleware/application.js new file mode 100644 index 00000000..316cd4cd --- /dev/null +++ b/src/api/middleware/application.js @@ -0,0 +1,16 @@ +import CompanyApplication, { CompanyApplicationRules } from "../../models/CompanyApplication.js"; + +export const exceededCreationTimeLimit = async (email) => { + const cursor = await CompanyApplication.findOne({ email, isVerified: false }).exec(); + if (cursor !== null && Date.now() - cursor.submittedAt < 5000 * 60) { + throw new Error(CompanyApplicationRules.APPLICATION_RECENTLY_CREATED.msg); + } + return true; +}; + +export const deleteApplications = async (email) => { + await CompanyApplication.deleteMany({ email: email, isVerified: false }).catch(function(error) { + console.error(error); + throw (error); // Failure + }); +}; diff --git a/src/api/middleware/validators/application.js b/src/api/middleware/validators/application.js index ed8ec1df..59cd85c9 100644 --- a/src/api/middleware/validators/application.js +++ b/src/api/middleware/validators/application.js @@ -6,7 +6,7 @@ import ValidationReasons from "./validationReasons.js"; import { checkDuplicatedEmail, valuesInSet, ensureArray } from "./validatorUtils.js"; import CompanyApplicationConstants from "../../../models/constants/CompanyApplication.js"; import CompanyConstants from "../../../models/constants/Company.js"; -import { applicationUniqueness, exceededCreationTimeLimit, CompanyApplicationProps } from "../../../models/CompanyApplication.js"; +import { applicationUniqueness, CompanyApplicationProps } from "../../../models/CompanyApplication.js"; import ApplicationStatus from "../../../models/constants/ApplicationStatus.js"; import { password } from "./auth.js"; @@ -19,7 +19,6 @@ export const create = useExpressValidators([ .bail() .custom(checkDuplicatedEmail).bail() .custom(applicationUniqueness) - .custom(exceededCreationTimeLimit) .trim(), password, diff --git a/src/api/routes/application.js b/src/api/routes/application.js index db15c004..8828cf13 100644 --- a/src/api/routes/application.js +++ b/src/api/routes/application.js @@ -1,7 +1,10 @@ import { Router } from "express"; import * as validators from "../middleware/validators/application.js"; import ApplicationService from "../../services/application.js"; -import CompanyApplication from "../../models/CompanyApplication.js"; +import * as applicationMiddleware from "../middleware/application.js"; +import { validToken } from "../middleware/auth.js"; +import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; +import * as validatorsd from "../middleware/validators/auth.js"; const router = Router(); @@ -13,24 +16,31 @@ export default (app) => { * Creates a new Company Application */ router.post("/", validators.create, async (req, res, next) => { - - await CompanyApplication.deleteMany({ email: req.body.email, isVerified: false }).catch(function(error) { - console.error(error); - return next(error); // Failure - }); - - try { + await applicationMiddleware.exceededCreationTimeLimit(req.body.email); + await applicationMiddleware.deleteApplications(req.body.email); const applicationService = new ApplicationService(); // This is safe since the service is destructuring the passed object and the fields have been validated const application = await applicationService.create(req.body); const link = applicationService.buildConfirmationLink(application._id); // ObjectId(application) - applicationService.sendConfirmationNotification(application.email, link); + await applicationService.sendConfirmationNotification(application.email, link); return res.json(application); } catch (err) { console.error(err); return next(err); } }); + router.get("/recover/:token/confirm", validatorsd.confirmRecover, validToken, (req, res) => res.status(HTTPStatus.OK).json({})); + + router.post("/recover/:token/confirm", validatorsd.finishRecover, validToken, async (req, res, next) => { + const { id } = req.locals.token; + try { + await new ApplicationService().applicationValidation(id); + return res.status(HTTPStatus.OK).json({}); + } catch (err) { + console.error(err); + return next(err); + } + }); }; diff --git a/src/email-templates/companyApplicationConfirmation.js b/src/email-templates/companyApplicationConfirmation.js index d1ce9d02..7745145c 100644 --- a/src/email-templates/companyApplicationConfirmation.js +++ b/src/email-templates/companyApplicationConfirmation.js @@ -1,5 +1,5 @@ export const APPLICATION_CONFIRMATION = (link) => ({ subject: "Confirm your NIJobs application", - template: "request_password_recovery", + template: "confirm-application", context: { link }, }); diff --git a/src/models/CompanyApplication.js b/src/models/CompanyApplication.js index 01af0236..b3e5fd53 100644 --- a/src/models/CompanyApplication.js +++ b/src/models/CompanyApplication.js @@ -34,9 +34,8 @@ export const CompanyApplicationRules = Object.freeze({ msg: "company-application-already-reviewed", }, APPLICATION_RECENTLY_CREATED: { - validator: validateExceededCreationTimeLimit, - msg: "application-created-in-less-than-five-minutes-ago" - } + msg: "company-application-already-created-less-than-5-minutes-ago", + }, }); export const CompanyApplicationProps = { @@ -134,23 +133,6 @@ export const applicationUniqueness = async (email) => { return true; }; -export const exceededCreationTimeLimit = async (email) => { - const cursor = await CompanyApplication.findOne({ email, isVerified: false }).exec(); - if (cursor !== null && Date.now() - cursor.submittedAt < 5000 * 60) { - throw new Error(CompanyApplicationRules.APPLICATION_RECENTLY_CREATED.msg); - } - return true; -}; - -async function validateExceededCreationTimeLimit(value) { - try { - await applicationUniqueness(value); - } catch (e) { - return false; - } - return true; -} - async function validateSingleActiveApplication(value) { try { await applicationUniqueness(value); @@ -176,6 +158,12 @@ export const isRejectable = (application) => { return true; }; + +CompanyApplicationSchema.methods.companyValidation = function() { + if (this.isVerified) throw new Error("Application was already validated by the company"); + this.isVerified = true; +}; + CompanyApplicationSchema.methods.approve = function() { isApprovable(this); this.approvedAt = Date.now(); diff --git a/src/services/application.js b/src/services/application.js index 3012cc40..b739294c 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -236,6 +236,10 @@ class CompanyApplicationService { throw err; } } + async applicationValidation(id) { + const application = await this.findById(id); + application.companyValidation(); + } } export default CompanyApplicationService; From 7fe08b574a7ad6c513c18255cf238068aeaf7523 Mon Sep 17 00:00:00 2001 From: Francisco Cardoso Date: Thu, 26 Jan 2023 13:05:05 +0000 Subject: [PATCH 05/30] Making the program send a confirmation email when registing Co-authored-by: Daniel Ferreira --- .env | 4 ++-- src/api/middleware/validators/application.js | 14 ++++++++++++++ src/api/routes/application.js | 9 ++++----- src/models/CompanyApplication.js | 5 +++-- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/.env b/.env index 9f7f72ce..74627e90 100644 --- a/.env +++ b/.env @@ -21,7 +21,7 @@ JWT_SECRET=Lendas contam que o Rui foi membro do IEEE. PASSWORD_RECOVERY_LINK=https://localhost:3000/recover # Froantend Application Confirmation Base Route -APPLICATION_CONFIRMATION_LINK=https://villate.org/eletricidade/fluxo.html +APPLICATION_CONFIRMATION_LINK=https://localhost:3000/validate # Specifies the port in which the app will be exposed PORT=8087 @@ -53,7 +53,7 @@ MAIL_FROM_PASSWORD= # Cloudinary API URL to save images CLOUDINARY_URL= -# Hostname of the application (where the webserver will be served) - without the trailing '/' +# Hostname of the application (where the webserver will be served) - without the trailing '/' WEBSERVER_HOST=https://localhost:8087 # Path to save file uploads, the path must be relative to the root of the project - Defaults to static diff --git a/src/api/middleware/validators/application.js b/src/api/middleware/validators/application.js index 59cd85c9..d5485291 100644 --- a/src/api/middleware/validators/application.js +++ b/src/api/middleware/validators/application.js @@ -112,3 +112,17 @@ export const search = useExpressValidators([ .custom(sortByParamValidator) .customSanitizer(parseSortByField), ]); + + +export const token = param("token", ValidationReasons.DEFAULT) + .exists().withMessage(ValidationReasons.REQUIRED).bail() + .isString().withMessage(ValidationReasons.STRING) + .trim(); + +export const confirmValidation = useExpressValidators([ + token, +]); + +export const finishValidation = useExpressValidators([ + token, +]); diff --git a/src/api/routes/application.js b/src/api/routes/application.js index 8828cf13..880e4a8a 100644 --- a/src/api/routes/application.js +++ b/src/api/routes/application.js @@ -4,8 +4,6 @@ import ApplicationService from "../../services/application.js"; import * as applicationMiddleware from "../middleware/application.js"; import { validToken } from "../middleware/auth.js"; import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; -import * as validatorsd from "../middleware/validators/auth.js"; - const router = Router(); @@ -30,10 +28,11 @@ export default (app) => { return next(err); } }); - router.get("/recover/:token/confirm", validatorsd.confirmRecover, validToken, (req, res) => res.status(HTTPStatus.OK).json({})); - router.post("/recover/:token/confirm", validatorsd.finishRecover, validToken, async (req, res, next) => { - const { id } = req.locals.token; + router.get("/validate/:token/confirm", validators.confirmValidation, validToken, (req, res) => res.status(HTTPStatus.OK).json({})); + + router.post("/validate/:token/confirm", validators.finishValidation, validToken, async (req, res, next) => { + const { _id: id } = req.locals.token; try { await new ApplicationService().applicationValidation(id); return res.status(HTTPStatus.OK).json({}); diff --git a/src/models/CompanyApplication.js b/src/models/CompanyApplication.js index b3e5fd53..988d52b3 100644 --- a/src/models/CompanyApplication.js +++ b/src/models/CompanyApplication.js @@ -124,8 +124,8 @@ export const applicationUniqueness = async (email) => { const existingApplications = await CompanyApplication.find({ email }); if (existingApplications.some((application) => (application.state === ApplicationStatus.PENDING || - application.state === ApplicationStatus.APPROVED) && - application.isVerified) + application.state === ApplicationStatus.APPROVED) && + application.isVerified) ) { throw new Error(CompanyApplicationRules.ONLY_ONE_APPLICATION_ACTIVE_PER_EMAIL.msg); } @@ -162,6 +162,7 @@ export const isRejectable = (application) => { CompanyApplicationSchema.methods.companyValidation = function() { if (this.isVerified) throw new Error("Application was already validated by the company"); this.isVerified = true; + return this.save({ validateModifiedOnly: true }); }; CompanyApplicationSchema.methods.approve = function() { From ca019bbe475b5555d5c31129a5614d686d8d4f7d Mon Sep 17 00:00:00 2001 From: Francisco Cardoso Date: Sun, 29 Jan 2023 14:18:04 +0000 Subject: [PATCH 06/30] Fixing order in wich emails are sent to company when creating an application Co-authored-by: Daniel Ferreira --- .env | 6 ++-- .eslintrc | 4 +-- src/api/routes/application.js | 5 ---- .../companyApplicationApproval.js | 6 ++++ src/lib/emailService.js | 1 + src/models/CompanyApplication.js | 2 +- src/services/application.js | 29 ++++++++++++------- 7 files changed, 31 insertions(+), 22 deletions(-) diff --git a/.env b/.env index 74627e90..c7e00fc8 100644 --- a/.env +++ b/.env @@ -21,7 +21,7 @@ JWT_SECRET=Lendas contam que o Rui foi membro do IEEE. PASSWORD_RECOVERY_LINK=https://localhost:3000/recover # Froantend Application Confirmation Base Route -APPLICATION_CONFIRMATION_LINK=https://localhost:3000/validate +APPLICATION_CONFIRMATION_LINK=https://localhost:8087/apply/company/validate/ # Specifies the port in which the app will be exposed PORT=8087 @@ -45,10 +45,10 @@ ACCESS_CONTROL_ALLOW_ORIGINS= # Check this for details on how to configure your personal account for testing (https://support.google.com/accounts/answer/185833?p=InvalidSecondFactor&visit_id=637446218993181653-2339409452&rd=1) # The email address from which the emails are sent -MAIL_FROM= +MAIL_FROM=jacky88@ethereal.email # Password for email above -MAIL_FROM_PASSWORD= +MAIL_FROM_PASSWORD=PgAnnVsAa6Sg8zJp6t # Cloudinary API URL to save images CLOUDINARY_URL= diff --git a/.eslintrc b/.eslintrc index 8ff0b7eb..5aa42c22 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,4 +1,4 @@ -{ +{ "extends": [ "eslint:recommended" ], @@ -99,6 +99,6 @@ "no-var": "error", "prefer-const": ["error", { "destructuring": "all" }], "prefer-template": "error", - "template-curly-spacing": "error", + "template-curly-spacing": "error" } } diff --git a/src/api/routes/application.js b/src/api/routes/application.js index 880e4a8a..a0318561 100644 --- a/src/api/routes/application.js +++ b/src/api/routes/application.js @@ -20,17 +20,12 @@ export default (app) => { const applicationService = new ApplicationService(); // This is safe since the service is destructuring the passed object and the fields have been validated const application = await applicationService.create(req.body); - const link = applicationService.buildConfirmationLink(application._id); // ObjectId(application) - await applicationService.sendConfirmationNotification(application.email, link); return res.json(application); } catch (err) { console.error(err); return next(err); } }); - - router.get("/validate/:token/confirm", validators.confirmValidation, validToken, (req, res) => res.status(HTTPStatus.OK).json({})); - router.post("/validate/:token/confirm", validators.finishValidation, validToken, async (req, res, next) => { const { _id: id } = req.locals.token; try { diff --git a/src/email-templates/companyApplicationApproval.js b/src/email-templates/companyApplicationApproval.js index 626aba37..a4423b35 100644 --- a/src/email-templates/companyApplicationApproval.js +++ b/src/email-templates/companyApplicationApproval.js @@ -8,6 +8,11 @@ export const NEW_COMPANY_APPLICATION_COMPANY = (companyName, applicationId) => ( template: "new_company_application_company", context: { companyName, applicationId }, }); +export const APPLICATION_CONFIRMATION = (link) => ({ + subject: "Confirm your NIJobs application", + template: "confirm-application", + context: { link }, +}); export const APPROVAL_NOTIFICATION = (companyName) => ({ subject: "Welcome to NIJobs!", template: "approval_notification", @@ -18,3 +23,4 @@ export const REJECTION_NOTIFICATION = (companyName) => ({ template: "rejection_notification", context: { companyName }, }); + diff --git a/src/lib/emailService.js b/src/lib/emailService.js index 682c7f42..d48e7a58 100644 --- a/src/lib/emailService.js +++ b/src/lib/emailService.js @@ -17,6 +17,7 @@ export class EmailService { }, connectionTimeout: 30000 }); + console.log("transporter"); transporter.use("compile", hbs({ viewEngine: { diff --git a/src/models/CompanyApplication.js b/src/models/CompanyApplication.js index 988d52b3..90090ca4 100644 --- a/src/models/CompanyApplication.js +++ b/src/models/CompanyApplication.js @@ -85,7 +85,7 @@ export const CompanyApplicationProps = { }, isVerified: { type: Boolean, - default: false, + default: true, }, }; diff --git a/src/services/application.js b/src/services/application.js index b739294c..a02066af 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -42,18 +42,15 @@ class CompanyApplicationService { companyName, motivation, submittedAt: Date.now(), + isVerified: false, }); - + console.log("criar"); + const link = this.buildConfirmationLink(application._id); await EmailService.sendMail({ - to: config.mail_from, - ...NEW_COMPANY_APPLICATION_ADMINS(application.email, companyName, motivation) + to: email, + ...APPLICATION_CONFIRMATION(link), }); - - await EmailService.sendMail({ - to: application.email, - ...NEW_COMPANY_APPLICATION_COMPANY(companyName, application._id.toString()) - }); - + console.log("Criado"); return application.toObject(); } @@ -76,7 +73,7 @@ class CompanyApplicationService { return { totalDocCount, applications: - [...(await CompanyApplication.find({}) + [...(await CompanyApplication.find({ isVerified: true }) .sort(sortingOptions || { submittedAt: "desc" }) .skip(offset) .limit(limit) @@ -120,6 +117,7 @@ class CompanyApplicationService { if (submissionDateFrom || submissionDateTo) filterQueries.push(this.buildSubmissionDateFilter({ from: submissionDateFrom, to: submissionDateTo })); + filterQueries.push({ isVerify: true }); return filterQueries; } @@ -222,7 +220,7 @@ class CompanyApplicationService { buildConfirmationLink(id) { const token = generateToken({ _id: id }, config.jwt_secret, RECOVERY_LINK_EXPIRATION); - return `${config.application_confirmation_link}/${token}`; + return `${config.application_confirmation_link}/${token}/confirm`; } async sendConfirmationNotification(email, link) { @@ -239,6 +237,15 @@ class CompanyApplicationService { async applicationValidation(id) { const application = await this.findById(id); application.companyValidation(); + await EmailService.sendMail({ + to: config.mail_from, + ...NEW_COMPANY_APPLICATION_ADMINS(application.email, application.companyName, application.motivation) + }); + + await EmailService.sendMail({ + to: application.email, + ...NEW_COMPANY_APPLICATION_COMPANY(application.companyName, application._id.toString()) + }); } } From 74c964a3a5267237da92994f0957ec7f10af1ff2 Mon Sep 17 00:00:00 2001 From: dsantosferreira Date: Fri, 3 Feb 2023 10:31:52 +0000 Subject: [PATCH 07/30] Add unverified state Co-authored-by: Francisco Cardoso --- src/models/CompanyApplication.js | 3 ++- src/models/constants/ApplicationStatus.js | 1 + src/services/application.js | 3 +-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/models/CompanyApplication.js b/src/models/CompanyApplication.js index 90090ca4..ef75a732 100644 --- a/src/models/CompanyApplication.js +++ b/src/models/CompanyApplication.js @@ -94,7 +94,8 @@ const CompanyApplicationSchema = new Schema(CompanyApplicationProps); CompanyApplicationSchema.index({ companyName: "text" }); CompanyApplicationSchema.virtual("state").get(function() { - if (!this.approvedAt && !this.rejectedAt) return ApplicationStatus.PENDING; + if (!this.isVerified) return ApplicationStatus.UNVERIFIED; + else if (!this.approvedAt && !this.rejectedAt) return ApplicationStatus.PENDING; else if (this.approvedAt) return ApplicationStatus.APPROVED; else return ApplicationStatus.REJECTED; }); diff --git a/src/models/constants/ApplicationStatus.js b/src/models/constants/ApplicationStatus.js index eb2bcca2..e283fff9 100644 --- a/src/models/constants/ApplicationStatus.js +++ b/src/models/constants/ApplicationStatus.js @@ -1,4 +1,5 @@ const ApplicationStatus = Object.freeze({ + "UNVERIFIED": "UNVERIFIED", "PENDING": "PENDING", "APPROVED": "APPROVED", "REJECTED": "REJECTED", diff --git a/src/services/application.js b/src/services/application.js index a02066af..afb5b177 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -73,7 +73,7 @@ class CompanyApplicationService { return { totalDocCount, applications: - [...(await CompanyApplication.find({ isVerified: true }) + [...(await CompanyApplication.find({}) .sort(sortingOptions || { submittedAt: "desc" }) .skip(offset) .limit(limit) @@ -117,7 +117,6 @@ class CompanyApplicationService { if (submissionDateFrom || submissionDateTo) filterQueries.push(this.buildSubmissionDateFilter({ from: submissionDateFrom, to: submissionDateTo })); - filterQueries.push({ isVerify: true }); return filterQueries; } From 2a57135b882699b1954237291a51303df5d37240 Mon Sep 17 00:00:00 2001 From: Francisco Cardoso Date: Wed, 8 Feb 2023 19:29:19 +0000 Subject: [PATCH 08/30] Adding custom errors for token validation Co-authored-by: Daniel Ferreira --- src/api/middleware/application.js | 5 +++-- src/api/middleware/auth.js | 19 ++++++++++--------- src/api/middleware/validators/application.js | 6 +----- .../validators/validationReasons.js | 1 + src/lib/emailService.js | 12 ++++++++++-- src/lib/token.js | 13 ++++++++++--- src/models/CompanyApplication.js | 5 ++++- src/services/application.js | 5 +++-- 8 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/api/middleware/application.js b/src/api/middleware/application.js index 316cd4cd..904ef3b7 100644 --- a/src/api/middleware/application.js +++ b/src/api/middleware/application.js @@ -1,9 +1,10 @@ import CompanyApplication, { CompanyApplicationRules } from "../../models/CompanyApplication.js"; - +import { APIError, ErrorTypes } from "./errorHandler.js"; +import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; export const exceededCreationTimeLimit = async (email) => { const cursor = await CompanyApplication.findOne({ email, isVerified: false }).exec(); if (cursor !== null && Date.now() - cursor.submittedAt < 5000 * 60) { - throw new Error(CompanyApplicationRules.APPLICATION_RECENTLY_CREATED.msg); + throw new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, CompanyApplicationRules.APPLICATION_RECENTLY_CREATED); } return true; }; diff --git a/src/api/middleware/auth.js b/src/api/middleware/auth.js index a469b1e5..48c5539c 100644 --- a/src/api/middleware/auth.js +++ b/src/api/middleware/auth.js @@ -78,15 +78,16 @@ export const hasAdminPrivileges = async (req, res, next) => { }; export const validToken = (req, res, next) => { - const decoded = verifyAndDecodeToken(req.params.token, config.jwt_secret); - - if (!decoded) { - return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.INVALID_TOKEN)); - } + try { + const decoded = verifyAndDecodeToken(req.params.token, config.jwt_secret, next); - storeInLocals(req, { - token: decoded, - }); + storeInLocals(req, { + token: decoded, + }); - return next(); + return next(); + } catch (err) { + console.log(err); + return next(err); + } }; diff --git a/src/api/middleware/validators/application.js b/src/api/middleware/validators/application.js index d5485291..c78203e2 100644 --- a/src/api/middleware/validators/application.js +++ b/src/api/middleware/validators/application.js @@ -119,10 +119,6 @@ export const token = param("token", ValidationReasons.DEFAULT) .isString().withMessage(ValidationReasons.STRING) .trim(); -export const confirmValidation = useExpressValidators([ - token, -]); - export const finishValidation = useExpressValidators([ - token, + token.exists().withMessage(ValidationReasons.NON_EXISTING_APPLICATION).bail(), ]); diff --git a/src/api/middleware/validators/validationReasons.js b/src/api/middleware/validators/validationReasons.js index 8ab305e1..cd4b767c 100644 --- a/src/api/middleware/validators/validationReasons.js +++ b/src/api/middleware/validators/validationReasons.js @@ -41,6 +41,7 @@ const ValidationReasons = Object.freeze({ OFFER_EDIT_PERIOD_OVER: (value) => `offer-edit-period-over:${value}-hours`, INVALID_QUERY_TOKEN: "invalid-query-token", INVALID_TOKEN: "invalid-token", + EXPIRED_TOKEN: "expired-token", JOB_MIN_DURATION_NOT_SPECIFIED: "job-max-duration-requires-job-min-duration", REGISTRATION_FINISHED: "registration-already-finished", REGISTRATION_NOT_FINISHED: "registration-not-finished-yet", diff --git a/src/lib/emailService.js b/src/lib/emailService.js index d48e7a58..2043cede 100644 --- a/src/lib/emailService.js +++ b/src/lib/emailService.js @@ -6,7 +6,7 @@ export class EmailService { async init({ email: user, password: pass }) { this.email = user; - const transporter = await nodemailer.createTransport({ + /* const transporter = await nodemailer.createTransport({ pool: true, host: "smtp.gmail.com", port: 465, @@ -17,7 +17,15 @@ export class EmailService { }, connectionTimeout: 30000 }); - console.log("transporter"); + console.log("transporter");*/ + const transporter = nodemailer.createTransport({ + host: "smtp.ethereal.email", + port: 587, + auth: { + user: "naomie.koelpin2@ethereal.email", + pass: "NGEVbMnTZzyA3MQD3V" + } + }); transporter.use("compile", hbs({ viewEngine: { diff --git a/src/lib/token.js b/src/lib/token.js index 171906bf..5728271a 100644 --- a/src/lib/token.js +++ b/src/lib/token.js @@ -1,4 +1,7 @@ import jwt from "jsonwebtoken"; +import { APIError, ErrorTypes } from "../api/middleware/errorHandler.js"; +import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; +import ValidationReasons from "../api/middleware/validators/validationReasons.js"; export const generateToken = (data, secret, expiresInSeconds) => jwt.sign( { ...data }, @@ -6,10 +9,14 @@ export const generateToken = (data, secret, expiresInSeconds) => jwt.sign( { expiresIn: `${expiresInSeconds} seconds`, algorithm: "HS256" } ); -export const verifyAndDecodeToken = (token, secret) => { +export const verifyAndDecodeToken = (token, secret, next) => { try { return jwt.verify(token, secret, { algorithm: "HS256" }); - } catch (err) { - return null; + } catch (jwtErr) { + if (jwtErr.name === "TokenExpiredError") { + return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.EXPIRED_TOKEN)); + } else { + return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.INVALID_TOKEN)); + } } }; diff --git a/src/models/CompanyApplication.js b/src/models/CompanyApplication.js index ef75a732..c51b4b47 100644 --- a/src/models/CompanyApplication.js +++ b/src/models/CompanyApplication.js @@ -2,6 +2,9 @@ import mongoose from "mongoose"; import ApplicationStatus from "./constants/ApplicationStatus.js"; import CompanyApplicationConstants from "./constants/CompanyApplication.js"; import { checkDuplicatedEmail } from "../api/middleware/validators/validatorUtils.js"; +import { APIError, ErrorTypes } from "../api/middleware/errorHandler.js"; +import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; +import ValidationReasons from "../api/middleware/validators/validationReasons.js"; const { Schema } = mongoose; @@ -161,7 +164,7 @@ export const isRejectable = (application) => { CompanyApplicationSchema.methods.companyValidation = function() { - if (this.isVerified) throw new Error("Application was already validated by the company"); + if (this.isVerified) throw new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.ALREADY_VALIDATED); this.isVerified = true; return this.save({ validateModifiedOnly: true }); }; diff --git a/src/services/application.js b/src/services/application.js index afb5b177..87feed79 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -5,6 +5,7 @@ import { RECOVERY_LINK_EXPIRATION } from "../models/constants/ApplicationStatus. import { APPLICATION_CONFIRMATION } from "../email-templates/companyApplicationConfirmation.js"; import AccountService from "./account.js"; import EmailService from "../lib/emailService.js"; +import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; import { NEW_COMPANY_APPLICATION_ADMINS, NEW_COMPANY_APPLICATION_COMPANY, @@ -12,6 +13,8 @@ import { REJECTION_NOTIFICATION, } from "../email-templates/companyApplicationApproval.js"; import config from "../config/env.js"; +import { APIError, ErrorTypes } from "../api/middleware/errorHandler.js"; +import ValidationReasons from "../api/middleware/validators/validationReasons.js"; export class CompanyApplicationNotFound extends Error { constructor(msg) { @@ -44,13 +47,11 @@ class CompanyApplicationService { submittedAt: Date.now(), isVerified: false, }); - console.log("criar"); const link = this.buildConfirmationLink(application._id); await EmailService.sendMail({ to: email, ...APPLICATION_CONFIRMATION(link), }); - console.log("Criado"); return application.toObject(); } From 431aacc9344f80accfbffe503ab214c9981af81b Mon Sep 17 00:00:00 2001 From: Francisco Cardoso Date: Sat, 11 Feb 2023 14:36:07 +0000 Subject: [PATCH 09/30] Changed emails templates and link from application validation expiration time Co-authored-by: Daniel Ferreira --- .env | 8 ++-- src/api/middleware/application.js | 20 ++++----- src/api/middleware/auth.js | 12 +++-- .../validators/validationReasons.js | 1 + src/api/routes/application.js | 13 ++++-- .../companyApplicationApproval.js | 1 - .../confirm-application.handlebars | 3 +- ...new_company_application_company.handlebars | 7 +-- src/lib/emailService.js | 19 ++------ src/lib/token.js | 15 +------ src/models/CompanyApplication.js | 18 ++++---- src/models/constants/ApplicationStatus.js | 2 +- src/services/application.js | 44 +++++++++++++------ 13 files changed, 82 insertions(+), 81 deletions(-) diff --git a/.env b/.env index c7e00fc8..a2ad7f7f 100644 --- a/.env +++ b/.env @@ -20,8 +20,8 @@ JWT_SECRET=Lendas contam que o Rui foi membro do IEEE. # Frontend Password Recovery Base Route PASSWORD_RECOVERY_LINK=https://localhost:3000/recover -# Froantend Application Confirmation Base Route -APPLICATION_CONFIRMATION_LINK=https://localhost:8087/apply/company/validate/ +# Frontend Application Confirmation Base Route +APPLICATION_CONFIRMATION_LINK=https://localhost:3000/apply/company/validate/ # Specifies the port in which the app will be exposed PORT=8087 @@ -45,10 +45,10 @@ ACCESS_CONTROL_ALLOW_ORIGINS= # Check this for details on how to configure your personal account for testing (https://support.google.com/accounts/answer/185833?p=InvalidSecondFactor&visit_id=637446218993181653-2339409452&rd=1) # The email address from which the emails are sent -MAIL_FROM=jacky88@ethereal.email +MAIL_FROM= # Password for email above -MAIL_FROM_PASSWORD=PgAnnVsAa6Sg8zJp6t +MAIL_FROM_PASSWORD= # Cloudinary API URL to save images CLOUDINARY_URL= diff --git a/src/api/middleware/application.js b/src/api/middleware/application.js index 904ef3b7..66c181f7 100644 --- a/src/api/middleware/application.js +++ b/src/api/middleware/application.js @@ -1,17 +1,13 @@ import CompanyApplication, { CompanyApplicationRules } from "../../models/CompanyApplication.js"; import { APIError, ErrorTypes } from "./errorHandler.js"; import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; -export const exceededCreationTimeLimit = async (email) => { - const cursor = await CompanyApplication.findOne({ email, isVerified: false }).exec(); - if (cursor !== null && Date.now() - cursor.submittedAt < 5000 * 60) { - throw new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, CompanyApplicationRules.APPLICATION_RECENTLY_CREATED); - } - return true; -}; +import { VALIDATION_LINK_EXPIRATION } from "../../models/constants/ApplicationStatus.js"; +import { SECOND_IN_MS } from "../../models/constants/TimeConstants.js"; -export const deleteApplications = async (email) => { - await CompanyApplication.deleteMany({ email: email, isVerified: false }).catch(function(error) { - console.error(error); - throw (error); // Failure - }); +export const exceededCreationTimeLimit = async (req, res, next) => { + const application = await CompanyApplication.findOne({ email: req.body.email, isVerified: false }); + if (application !== null && Date.now() < application.submittedAt.getTime() + (VALIDATION_LINK_EXPIRATION * SECOND_IN_MS)) { + return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, CompanyApplicationRules.APPLICATION_RECENTLY_CREATED.msg)); + } + return next(); }; diff --git a/src/api/middleware/auth.js b/src/api/middleware/auth.js index 48c5539c..78bba6dc 100644 --- a/src/api/middleware/auth.js +++ b/src/api/middleware/auth.js @@ -79,15 +79,19 @@ export const hasAdminPrivileges = async (req, res, next) => { export const validToken = (req, res, next) => { try { - const decoded = verifyAndDecodeToken(req.params.token, config.jwt_secret, next); + const decoded = verifyAndDecodeToken(req.params.token, config.jwt_secret); storeInLocals(req, { token: decoded, }); return next(); - } catch (err) { - console.log(err); - return next(err); + } catch (jwtErr) { + console.log(jwtErr); + if (jwtErr.name === "TokenExpiredError") { + return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.EXPIRED_TOKEN)); + } else { + return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.INVALID_TOKEN)); + } } }; diff --git a/src/api/middleware/validators/validationReasons.js b/src/api/middleware/validators/validationReasons.js index cd4b767c..62b884a8 100644 --- a/src/api/middleware/validators/validationReasons.js +++ b/src/api/middleware/validators/validationReasons.js @@ -49,6 +49,7 @@ const ValidationReasons = Object.freeze({ IMAGE_FORMAT: "formats-supported-png-jpeg-jpg", OFFER_BLOCKED_ADMIN: "offer-blocked-by-admin", OFFER_HIDDEN: "offer-is-hidden", + NON_EXISTING_APPLICATION: "application-does-not-exist", FILE_TOO_LARGE: (max) => `file-cant-be-larger-than-${max}MB`, MUST_BE_GREATER_THAN_OR_EQUAL_TO: (field) => `must-be-greater-than-or-equal-to:${field}`, APPLICATION_RECENTLY_CREATED: "application-created-in-less-than-five-minutes-ago", diff --git a/src/api/routes/application.js b/src/api/routes/application.js index a0318561..2c22a98b 100644 --- a/src/api/routes/application.js +++ b/src/api/routes/application.js @@ -1,9 +1,10 @@ import { Router } from "express"; import * as validators from "../middleware/validators/application.js"; -import ApplicationService from "../../services/application.js"; +import ApplicationService, { CompanyApplicationAlreadyValidated } from "../../services/application.js"; import * as applicationMiddleware from "../middleware/application.js"; import { validToken } from "../middleware/auth.js"; import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; +import { buildErrorResponse, ErrorTypes } from "../middleware/errorHandler.js"; const router = Router(); @@ -13,11 +14,10 @@ export default (app) => { /** * Creates a new Company Application */ - router.post("/", validators.create, async (req, res, next) => { + router.post("/", validators.create, applicationMiddleware.exceededCreationTimeLimit, async (req, res, next) => { try { - await applicationMiddleware.exceededCreationTimeLimit(req.body.email); - await applicationMiddleware.deleteApplications(req.body.email); const applicationService = new ApplicationService(); + await applicationService.deleteApplications(req.body.email); // This is safe since the service is destructuring the passed object and the fields have been validated const application = await applicationService.create(req.body); return res.json(application); @@ -32,6 +32,11 @@ export default (app) => { await new ApplicationService().applicationValidation(id); return res.status(HTTPStatus.OK).json({}); } catch (err) { + if (err instanceof CompanyApplicationAlreadyValidated) { + return res + .status(HTTPStatus.CONFLICT) + .json(buildErrorResponse(ErrorTypes.FORBIDDEN, [{ msg: err.message }])); + } console.error(err); return next(err); } diff --git a/src/email-templates/companyApplicationApproval.js b/src/email-templates/companyApplicationApproval.js index a4423b35..078677d4 100644 --- a/src/email-templates/companyApplicationApproval.js +++ b/src/email-templates/companyApplicationApproval.js @@ -23,4 +23,3 @@ export const REJECTION_NOTIFICATION = (companyName) => ({ template: "rejection_notification", context: { companyName }, }); - diff --git a/src/email-templates/confirm-application.handlebars b/src/email-templates/confirm-application.handlebars index aceaa777..3924bd9f 100644 --- a/src/email-templates/confirm-application.handlebars +++ b/src/email-templates/confirm-application.handlebars @@ -1,5 +1,6 @@

Confirm your NIJobs application

-

Please follow this link to finish the process. Note that the link will be expired in 5 minutes.

+

We have successfully received your application!

+

Please follow this link to finish the process. Note that the link will expire in 10 minutes.


If you did not request this or need anything else, please contact us at nijobs@aefeup.pt!


Sincerely,

diff --git a/src/email-templates/new_company_application_company.handlebars b/src/email-templates/new_company_application_company.handlebars index 8966ef10..4c03b7b8 100644 --- a/src/email-templates/new_company_application_company.handlebars +++ b/src/email-templates/new_company_application_company.handlebars @@ -1,8 +1,9 @@ -

We have successfully received your application!

-

We will now review your application, and in case you're approved, you will receive another email with further instructions in order to complete your registration.

+

Your application has been validated!

+

We will now review your application, and in case you're approved, you will receive another email with further instructions in order to complete your registration.

Your Application ID is {{applicationId}} and you registered {{companyName}}

+

Once you're approved, you will receive an email, and then you can log into NIJobs! Do not forget your password, you will need it on the first login.


If you did not request this or if you need anything else, don't hesitate to contact us at nijobs@aefeup.pt!


Sincerely,

-

NIJobs team at NIAEFEUP

\ No newline at end of file +

NIJobs team at NIAEFEUP

diff --git a/src/lib/emailService.js b/src/lib/emailService.js index 2043cede..d046f7ea 100644 --- a/src/lib/emailService.js +++ b/src/lib/emailService.js @@ -6,24 +6,13 @@ export class EmailService { async init({ email: user, password: pass }) { this.email = user; - /* const transporter = await nodemailer.createTransport({ - pool: true, - host: "smtp.gmail.com", - port: 465, - secure: true, - auth: { - user, - pass - }, - connectionTimeout: 30000 - }); - console.log("transporter");*/ const transporter = nodemailer.createTransport({ - host: "smtp.ethereal.email", + host: 'smtp.ethereal.email', port: 587, + secure: false, // true for 465, false for other ports auth: { - user: "naomie.koelpin2@ethereal.email", - pass: "NGEVbMnTZzyA3MQD3V" + user: "magdalen.labadie@ethereal.email", // generated ethereal user + pass: "GjdJdafFyj5svQBzJJ"// generated ethereal password } }); diff --git a/src/lib/token.js b/src/lib/token.js index 5728271a..be8ed801 100644 --- a/src/lib/token.js +++ b/src/lib/token.js @@ -1,7 +1,4 @@ import jwt from "jsonwebtoken"; -import { APIError, ErrorTypes } from "../api/middleware/errorHandler.js"; -import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; -import ValidationReasons from "../api/middleware/validators/validationReasons.js"; export const generateToken = (data, secret, expiresInSeconds) => jwt.sign( { ...data }, @@ -9,14 +6,4 @@ export const generateToken = (data, secret, expiresInSeconds) => jwt.sign( { expiresIn: `${expiresInSeconds} seconds`, algorithm: "HS256" } ); -export const verifyAndDecodeToken = (token, secret, next) => { - try { - return jwt.verify(token, secret, { algorithm: "HS256" }); - } catch (jwtErr) { - if (jwtErr.name === "TokenExpiredError") { - return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.EXPIRED_TOKEN)); - } else { - return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.INVALID_TOKEN)); - } - } -}; +export const verifyAndDecodeToken = (token, secret) => jwt.verify(token, secret, { algorithm: "HS256" }); diff --git a/src/models/CompanyApplication.js b/src/models/CompanyApplication.js index c51b4b47..e3887313 100644 --- a/src/models/CompanyApplication.js +++ b/src/models/CompanyApplication.js @@ -2,9 +2,7 @@ import mongoose from "mongoose"; import ApplicationStatus from "./constants/ApplicationStatus.js"; import CompanyApplicationConstants from "./constants/CompanyApplication.js"; import { checkDuplicatedEmail } from "../api/middleware/validators/validatorUtils.js"; -import { APIError, ErrorTypes } from "../api/middleware/errorHandler.js"; -import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; -import ValidationReasons from "../api/middleware/validators/validationReasons.js"; + const { Schema } = mongoose; @@ -37,8 +35,11 @@ export const CompanyApplicationRules = Object.freeze({ msg: "company-application-already-reviewed", }, APPLICATION_RECENTLY_CREATED: { - msg: "company-application-already-created-less-than-5-minutes-ago", + msg: "company-application-recently-created", }, + APPLICATION_ALREADY_VALIDATED: { + msg: "application-already-validated", + } }); export const CompanyApplicationProps = { @@ -127,9 +128,8 @@ function validateMutuallyExclusiveEvents(field) { export const applicationUniqueness = async (email) => { const existingApplications = await CompanyApplication.find({ email }); if (existingApplications.some((application) => - (application.state === ApplicationStatus.PENDING || - application.state === ApplicationStatus.APPROVED) && - application.isVerified) + application.state === ApplicationStatus.PENDING || + application.state === ApplicationStatus.APPROVED) ) { throw new Error(CompanyApplicationRules.ONLY_ONE_APPLICATION_ACTIVE_PER_EMAIL.msg); } @@ -164,7 +164,9 @@ export const isRejectable = (application) => { CompanyApplicationSchema.methods.companyValidation = function() { - if (this.isVerified) throw new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.ALREADY_VALIDATED); + if (this.isVerified) + throw new Error(CompanyApplicationRules.APPLICATION_ALREADY_VALIDATED.msg); + this.isVerified = true; return this.save({ validateModifiedOnly: true }); }; diff --git a/src/models/constants/ApplicationStatus.js b/src/models/constants/ApplicationStatus.js index e283fff9..72f35baf 100644 --- a/src/models/constants/ApplicationStatus.js +++ b/src/models/constants/ApplicationStatus.js @@ -7,4 +7,4 @@ const ApplicationStatus = Object.freeze({ export default ApplicationStatus; -export const RECOVERY_LINK_EXPIRATION = 300; +export const VALIDATION_LINK_EXPIRATION = 600; diff --git a/src/services/application.js b/src/services/application.js index 87feed79..9ea3f821 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -1,11 +1,10 @@ import CompanyApplication, { CompanyApplicationRules } from "../models/CompanyApplication.js"; import { generateToken } from "../lib/token.js"; import hash from "../lib/passwordHashing.js"; -import { RECOVERY_LINK_EXPIRATION } from "../models/constants/ApplicationStatus.js"; +import { VALIDATION_LINK_EXPIRATION } from "../models/constants/ApplicationStatus.js"; import { APPLICATION_CONFIRMATION } from "../email-templates/companyApplicationConfirmation.js"; import AccountService from "./account.js"; import EmailService from "../lib/emailService.js"; -import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; import { NEW_COMPANY_APPLICATION_ADMINS, NEW_COMPANY_APPLICATION_COMPANY, @@ -13,8 +12,7 @@ import { REJECTION_NOTIFICATION, } from "../email-templates/companyApplicationApproval.js"; import config from "../config/env.js"; -import { APIError, ErrorTypes } from "../api/middleware/errorHandler.js"; -import ValidationReasons from "../api/middleware/validators/validationReasons.js"; + export class CompanyApplicationNotFound extends Error { constructor(msg) { @@ -34,6 +32,12 @@ export class CompanyApplicationEmailAlreadyInUse extends Error { } } +export class CompanyApplicationAlreadyValidated extends Error { + constructor(msg) { + super(msg); + } +} + class CompanyApplicationService { async create({ @@ -219,7 +223,7 @@ class CompanyApplicationService { } buildConfirmationLink(id) { - const token = generateToken({ _id: id }, config.jwt_secret, RECOVERY_LINK_EXPIRATION); + const token = generateToken({ _id: id }, config.jwt_secret, VALIDATION_LINK_EXPIRATION); return `${config.application_confirmation_link}/${token}/confirm`; } @@ -234,19 +238,31 @@ class CompanyApplicationService { throw err; } } + async applicationValidation(id) { const application = await this.findById(id); - application.companyValidation(); - await EmailService.sendMail({ - to: config.mail_from, - ...NEW_COMPANY_APPLICATION_ADMINS(application.email, application.companyName, application.motivation) - }); - await EmailService.sendMail({ - to: application.email, - ...NEW_COMPANY_APPLICATION_COMPANY(application.companyName, application._id.toString()) - }); + try { + application.companyValidation(); + await EmailService.sendMail({ + to: config.mail_from, + ...NEW_COMPANY_APPLICATION_ADMINS(application.email, application.companyName, application.motivation) + }); + + await EmailService.sendMail({ + to: application.email, + ...NEW_COMPANY_APPLICATION_COMPANY(application.companyName, application._id.toString()) + }); + } catch (err) { + console.error(err); + throw new CompanyApplicationAlreadyValidated(CompanyApplicationRules.APPLICATION_ALREADY_VALIDATED.msg); + } + } + + async deleteApplications(email) { + await CompanyApplication.deleteMany({ email: email, isVerified: false }); } } + export default CompanyApplicationService; From a135fdf9467c260a38ee8a39c5218200b6867be9 Mon Sep 17 00:00:00 2001 From: Francisco Cardoso Date: Sun, 2 Apr 2023 20:51:23 +0100 Subject: [PATCH 10/30] Changing the order when the account is created so that it is created after validating the application --- src/api/routes/review.js | 1 + src/services/application.js | 42 ++++++++++++++++++++----------------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/api/routes/review.js b/src/api/routes/review.js index 27b459ea..46422fd6 100644 --- a/src/api/routes/review.js +++ b/src/api/routes/review.js @@ -82,6 +82,7 @@ export default (app) => { async (req, res, next) => { try { + /* TODO: check return account logic*/ const { account } = await (new ApplicationService()).approve(req.params.id); return res.json(account); } catch (err) { diff --git a/src/services/application.js b/src/services/application.js index 9ea3f821..58a51ad1 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -12,6 +12,7 @@ import { REJECTION_NOTIFICATION, } from "../email-templates/companyApplicationApproval.js"; import config from "../config/env.js"; +import Account from "../models/constants/Account.js"; export class CompanyApplicationNotFound extends Error { @@ -182,26 +183,9 @@ class CompanyApplicationService { console.error(e); throw new CompanyApplicationAlreadyReviewed(CompanyApplicationRules.CANNOT_REVIEW_TWICE.msg); } + return Account.findOne({ email: application.email }); - try { - const account = await (new AccountService()).registerCompany(application.email, application.password, application.companyName); - - await EmailService.sendMail({ - to: application.email, - ...APPROVAL_NOTIFICATION(application.companyName), - }); - - return { application, account }; - - } catch (err) { - console.error(`Error creating account for approved Company Application, rolling back approval of ${application._id}`, err); - application.undoApproval(); - if (err.name === "MongoServerError" && /E11000\s.*collection:\s.*\.accounts.*/.test(err.errmsg)) { - throw new CompanyApplicationEmailAlreadyInUse(CompanyApplicationRules.EMAIL_ALREADY_IN_USE.msg); - } else { - throw err; - } - } + /* TODO: Make offers unpending */ } async reject(id, reason, options) { @@ -257,6 +241,26 @@ class CompanyApplicationService { console.error(err); throw new CompanyApplicationAlreadyValidated(CompanyApplicationRules.APPLICATION_ALREADY_VALIDATED.msg); } + + try { + const account = await (new AccountService()).registerCompany(application.email, application.password, application.companyName); + + await EmailService.sendMail({ + to: application.email, + ...APPROVAL_NOTIFICATION(application.companyName), + }); + + return { application, account }; + + } catch (err) { + console.error(`Error creating account for approved Company Application, rolling back approval of ${application._id}`, err); + application.undoApproval(); + if (err.name === "MongoServerError" && /E11000\s.*collection:\s.*\.accounts.*/.test(err.errmsg)) { + throw new CompanyApplicationEmailAlreadyInUse(CompanyApplicationRules.EMAIL_ALREADY_IN_USE.msg); + } else { + throw err; + } + } } async deleteApplications(email) { From ba321035348dba9f7098ebc51b0db753a1d14838 Mon Sep 17 00:00:00 2001 From: dsantosferreira Date: Fri, 14 Apr 2023 23:23:53 +0100 Subject: [PATCH 11/30] Fixed frontend confirmation link --- .env | 2 +- src/services/application.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env b/.env index a2ad7f7f..b11bd6b5 100644 --- a/.env +++ b/.env @@ -21,7 +21,7 @@ JWT_SECRET=Lendas contam que o Rui foi membro do IEEE. PASSWORD_RECOVERY_LINK=https://localhost:3000/recover # Frontend Application Confirmation Base Route -APPLICATION_CONFIRMATION_LINK=https://localhost:3000/apply/company/validate/ +APPLICATION_CONFIRMATION_LINK=https://localhost:3000/apply/validate/ # Specifies the port in which the app will be exposed PORT=8087 diff --git a/src/services/application.js b/src/services/application.js index 58a51ad1..9657c0f2 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -208,7 +208,7 @@ class CompanyApplicationService { buildConfirmationLink(id) { const token = generateToken({ _id: id }, config.jwt_secret, VALIDATION_LINK_EXPIRATION); - return `${config.application_confirmation_link}/${token}/confirm`; + return `${config.application_confirmation_link}${token}/confirm`; } async sendConfirmationNotification(email, link) { From 5625a90fa629b41d4e535ad21e9e7102c8f6c03b Mon Sep 17 00:00:00 2001 From: dsantosferreira Date: Sat, 15 Apr 2023 00:54:16 +0100 Subject: [PATCH 12/30] Created new isPending attribute in Offer model and implemented creating of pending offers depending on application status Co-authored-by: Francisco Cardoso --- src/api/routes/offer.js | 11 ++++++++--- src/models/Offer.js | 4 ++++ src/services/offer.js | 2 ++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/api/routes/offer.js b/src/api/routes/offer.js index 0e8b3db7..40999d16 100644 --- a/src/api/routes/offer.js +++ b/src/api/routes/offer.js @@ -11,6 +11,9 @@ import ValidationReasons from "../middleware/validators/validationReasons.js"; import { or, when } from "../middleware/utils.js"; import OfferConstants from "../../models/constants/Offer.js"; import * as companyValidators from "../middleware/validators/company.js"; +import CompanyApplication from "../../models/CompanyApplication.js"; +import Account from "../../models/Account.js" +import ApplicationStatus from "../../models/constants/ApplicationStatus.js"; const router = Router(); @@ -97,11 +100,13 @@ export default (app) => { (req, res, next) => companyMiddleware.isNotDisabled(req.targetOwner)(req, res, next)), validators.offersDateSanitizers, async (req, res, next) => { - try { - + try { + const account = await Account.findOne({ company: req.targetOwner }); + const application = await CompanyApplication.findOne({ email: account.email }); const params = { ...req.body, - owner: req.targetOwner + owner: req.targetOwner, + isPending: application.state === ApplicationStatus.APPROVED ? false : true, }; const offer = await (new OfferService()).create(params); diff --git a/src/models/Offer.js b/src/models/Offer.js index f8b53fd9..2f529307 100644 --- a/src/models/Offer.js +++ b/src/models/Offer.js @@ -83,6 +83,10 @@ const OfferSchema = new Schema({ type: Boolean, default: false }, + isPending: { + type: Boolean, + default: false, + }, isArchived: { type: Boolean, default: false diff --git a/src/services/offer.js b/src/services/offer.js index 025e2094..c8ca7c03 100644 --- a/src/services/offer.js +++ b/src/services/offer.js @@ -35,6 +35,7 @@ class OfferService { fields, technologies, isHidden, + isPending, owner, location, coordinates, @@ -58,6 +59,7 @@ class OfferService { fields, technologies, isHidden, + isPending, owner, ownerName, ownerLogo, From bc95f0b4118056cbcab4f4939e79e76a2ce90e43 Mon Sep 17 00:00:00 2001 From: dsantosferreira Date: Mon, 17 Apr 2023 00:03:13 +0100 Subject: [PATCH 13/30] Set isPending of all company's offers to false when its application is approved Co-authored-by: Francisco Cardoso --- src/api/routes/offer.js | 2 +- src/api/routes/review.js | 9 ++++++--- src/services/application.js | 6 ++---- src/services/company.js | 12 ++++++++++++ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/api/routes/offer.js b/src/api/routes/offer.js index 40999d16..08b2f338 100644 --- a/src/api/routes/offer.js +++ b/src/api/routes/offer.js @@ -106,7 +106,7 @@ export default (app) => { const params = { ...req.body, owner: req.targetOwner, - isPending: application.state === ApplicationStatus.APPROVED ? false : true, + isPending: !(application.state === ApplicationStatus.APPROVED), }; const offer = await (new OfferService()).create(params); diff --git a/src/api/routes/review.js b/src/api/routes/review.js index 46422fd6..122fbc89 100644 --- a/src/api/routes/review.js +++ b/src/api/routes/review.js @@ -10,6 +10,8 @@ import ApplicationService, { } from "../../services/application.js"; import { buildErrorResponse, ErrorTypes } from "../middleware/errorHandler.js"; +import Company from "../../models/Company.js"; +import CompanyService from "../../services/company.js"; const router = Router(); @@ -82,9 +84,10 @@ export default (app) => { async (req, res, next) => { try { - /* TODO: check return account logic*/ - const { account } = await (new ApplicationService()).approve(req.params.id); - return res.json(account); + const account = await (new ApplicationService()).approve(req.params.id); + const company = await Company.findOne({ company: account.company }); + await (new CompanyService()).releaseOffers(company); + return res.json({account}); } catch (err) { console.error(err); if (err instanceof CompanyApplicationNotFound) { diff --git a/src/services/application.js b/src/services/application.js index 9657c0f2..04e1a37f 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -12,7 +12,7 @@ import { REJECTION_NOTIFICATION, } from "../email-templates/companyApplicationApproval.js"; import config from "../config/env.js"; -import Account from "../models/constants/Account.js"; +import Account from "../models/Account.js"; export class CompanyApplicationNotFound extends Error { @@ -183,9 +183,7 @@ class CompanyApplicationService { console.error(e); throw new CompanyApplicationAlreadyReviewed(CompanyApplicationRules.CANNOT_REVIEW_TWICE.msg); } - return Account.findOne({ email: application.email }); - - /* TODO: Make offers unpending */ + return Account.findOne({ email: application.email }); } async reject(id, reason, options) { diff --git a/src/services/company.js b/src/services/company.js index c3e42490..3649d7f3 100644 --- a/src/services/company.js +++ b/src/services/company.js @@ -8,6 +8,8 @@ import { import EmailService from "../lib/emailService.js"; import Account from "../models/Account.js"; import Company from "../models/Company.js"; +import Offer from "../models/Offer.js" + class CompanyService { getOffersInTimePeriod(owner, publishDate, publishEndDate, OfferModel) { return OfferModel.find({ @@ -196,6 +198,16 @@ class CompanyService { throw err; } } + + + async releaseOffers(companyId) { + try { + await Offer.updateMany({ company : companyId }, { $set: { "isPending" : false } }); + } catch (err) { + console.error(err); + throw err; + } + } } export default CompanyService; From 994509ae15f77444852c660b3ffe858ccbb1b929 Mon Sep 17 00:00:00 2001 From: dsantosferreira Date: Mon, 17 Apr 2023 00:45:53 +0100 Subject: [PATCH 14/30] Get all currently active offers endpoint only returns non-pending offers. Co-authored-by: Francisco Cardoso --- src/models/Offer.js | 4 ++++ src/services/company.js | 2 +- src/services/offer.js | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/models/Offer.js b/src/models/Offer.js index 2f529307..573b2ae8 100644 --- a/src/models/Offer.js +++ b/src/models/Offer.js @@ -165,6 +165,10 @@ OfferSchema.query.current = function() { return this.where(this.model.filterCurrent()); }; +OfferSchema.query.notPending= function(){ + return this.where({ isPending: false }); +} + /** * Currently active and non-hidden Offers */ diff --git a/src/services/company.js b/src/services/company.js index 3649d7f3..f13ae307 100644 --- a/src/services/company.js +++ b/src/services/company.js @@ -202,7 +202,7 @@ class CompanyService { async releaseOffers(companyId) { try { - await Offer.updateMany({ company : companyId }, { $set: { "isPending" : false } }); + await Offer.updateMany({ owner : companyId }, { $set: { "isPending" : false } }); } catch (err) { console.error(err); throw err; diff --git a/src/services/offer.js b/src/services/offer.js index c8ca7c03..14ee0358 100644 --- a/src/services/offer.js +++ b/src/services/offer.js @@ -372,6 +372,7 @@ class OfferService { selectSearchOffers(offers, showHidden, showAdminReason) { offers.current(); + offers.notPending(); if (!showHidden) offers.withoutHidden(); if (!showAdminReason) offers.select("-adminReason"); From 46f45813d188b86c833a39e74f25b76bf1863ba4 Mon Sep 17 00:00:00 2001 From: FranciscoCardoso913 Date: Tue, 27 Jun 2023 00:31:36 +0100 Subject: [PATCH 15/30] Fixed offers not updating isPending status after company is approved --- src/api/routes/offer.js | 6 ++---- src/api/routes/review.js | 6 +++--- src/services/company.js | 4 ++-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/api/routes/offer.js b/src/api/routes/offer.js index 08b2f338..ff87ec9d 100644 --- a/src/api/routes/offer.js +++ b/src/api/routes/offer.js @@ -12,7 +12,7 @@ import { or, when } from "../middleware/utils.js"; import OfferConstants from "../../models/constants/Offer.js"; import * as companyValidators from "../middleware/validators/company.js"; import CompanyApplication from "../../models/CompanyApplication.js"; -import Account from "../../models/Account.js" +import Account from "../../models/Account.js"; import ApplicationStatus from "../../models/constants/ApplicationStatus.js"; const router = Router(); @@ -100,7 +100,7 @@ export default (app) => { (req, res, next) => companyMiddleware.isNotDisabled(req.targetOwner)(req, res, next)), validators.offersDateSanitizers, async (req, res, next) => { - try { + try { const account = await Account.findOne({ company: req.targetOwner }); const application = await CompanyApplication.findOne({ email: account.email }); const params = { @@ -108,9 +108,7 @@ export default (app) => { owner: req.targetOwner, isPending: !(application.state === ApplicationStatus.APPROVED), }; - const offer = await (new OfferService()).create(params); - return res.json(offer); } catch (err) { console.error(err); diff --git a/src/api/routes/review.js b/src/api/routes/review.js index 122fbc89..dc1719d4 100644 --- a/src/api/routes/review.js +++ b/src/api/routes/review.js @@ -85,9 +85,9 @@ export default (app) => { try { const account = await (new ApplicationService()).approve(req.params.id); - const company = await Company.findOne({ company: account.company }); - await (new CompanyService()).releaseOffers(company); - return res.json({account}); + const company = await Company.findOne({ _id: account.company }); + await (new CompanyService()).releaseOffers(company._id); + return res.json({ account }); } catch (err) { console.error(err); if (err instanceof CompanyApplicationNotFound) { diff --git a/src/services/company.js b/src/services/company.js index f13ae307..5fa8a8bd 100644 --- a/src/services/company.js +++ b/src/services/company.js @@ -8,7 +8,7 @@ import { import EmailService from "../lib/emailService.js"; import Account from "../models/Account.js"; import Company from "../models/Company.js"; -import Offer from "../models/Offer.js" +import Offer from "../models/Offer.js"; class CompanyService { getOffersInTimePeriod(owner, publishDate, publishEndDate, OfferModel) { @@ -202,7 +202,7 @@ class CompanyService { async releaseOffers(companyId) { try { - await Offer.updateMany({ owner : companyId }, { $set: { "isPending" : false } }); + await Offer.updateMany({ owner: companyId }, { $set: { "isPending": false } }); } catch (err) { console.error(err); throw err; From 89b75e82af135fff80892a58a2c0f6d5d1413501 Mon Sep 17 00:00:00 2001 From: FranciscoCardoso913 Date: Tue, 27 Jun 2023 11:12:29 +0100 Subject: [PATCH 16/30] Route to get an application from a company Co-authored-by: Daniel Ferreira --- src/api/middleware/auth.js | 7 ++++++ src/api/middleware/validators/company.js | 4 ++++ src/api/routes/company.js | 27 ++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/src/api/middleware/auth.js b/src/api/middleware/auth.js index 78bba6dc..ffc69e6d 100644 --- a/src/api/middleware/auth.js +++ b/src/api/middleware/auth.js @@ -95,3 +95,10 @@ export const validToken = (req, res, next) => { } } }; + +export const hasCompanyAccess = (companyId) => (req, res, next) => { + if (!req.user?.company?._id.equals(companyId)) { + return next(new APIError(HTTPStatus.UNAUTHORIZED, ErrorTypes.FORBIDDEN, ValidationReasons.MUST_BE_ADMIN)); + } + return next(); +}; diff --git a/src/api/middleware/validators/company.js b/src/api/middleware/validators/company.js index 82fe9fa4..e9d71f16 100644 --- a/src/api/middleware/validators/company.js +++ b/src/api/middleware/validators/company.js @@ -134,3 +134,7 @@ export const edit = useExpressValidators([ .isString().withMessage(ValidationReasons.STRING).bail() .isURL().withMessage(ValidationReasons.URL), ]); + +export const getApplication = useExpressValidators([ + existingCompanyParamValidator, +]); diff --git a/src/api/routes/company.js b/src/api/routes/company.js index 01db8ab2..cb565f56 100644 --- a/src/api/routes/company.js +++ b/src/api/routes/company.js @@ -17,6 +17,9 @@ import * as fileMiddleware from "../middleware/files.js"; import OfferService from "../../services/offer.js"; import AccountService from "../../services/account.js"; import Offer from "../../models/Offer.js"; +import Account from "../../models/Account.js"; +import CompanyApplication from "../../models/CompanyApplication.js"; + const router = Router(); @@ -253,4 +256,28 @@ export default (app) => { } } ); + + /** + * Get the application of a company + */ + router.get("/:companyId/application", + or([ + authMiddleware.isAdmin, + authMiddleware.isGod, + (req, res, next) => authMiddleware.hasCompanyAccess(req.params.companyId)(req, res, next), + ], { status_code: HTTPStatus.UNAUTHORIZED, error_code: ErrorTypes.FORBIDDEN, msg: ValidationReasons.INSUFFICIENT_PERMISSIONS }), + validators.getApplication, + + + async (req, res, next) => { + + try { + const account = await Account.findOne({ "company": req.params.companyId }); + const application = await CompanyApplication.findOne({ "email": account.email }); + return res.json(application); + } catch (err) { + console.error(err); + return next(err); + } + }); }; From 96dfd74a9dd26f7b6f8845a2aff276460d486b05 Mon Sep 17 00:00:00 2001 From: FranciscoCardoso913 Date: Tue, 4 Jul 2023 10:32:42 +0100 Subject: [PATCH 17/30] Rewriting the emails to match the current flow. Co-authored-by: Daniel Ferreira --- .../approval_notification.handlebars | 10 +++++----- .../confirm-application.handlebars | 6 +++--- .../new_company_application_company.handlebars | 8 +++++--- src/services/application.js | 16 +++++++--------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/email-templates/approval_notification.handlebars b/src/email-templates/approval_notification.handlebars index cc7c3806..daf71e9a 100644 --- a/src/email-templates/approval_notification.handlebars +++ b/src/email-templates/approval_notification.handlebars @@ -1,9 +1,9 @@ -

Glad to have you on board, {{companyName}}!

-

We decided to accept your application, and you are just one step away from being able to use NIJobs!

-

Now, you can log in to NIJobs and complete your registration. -Once you finish, you'll be able to place some work offers!

+

We are delighted to have you on board, {{companyName}}!

+

We are pleased to inform you that your application has been accepted, and all the offers + you have created so far are now visible to the public!

+

Going forward, any offer you create will be immediately visible to the public audience.


-

If you need anything else, don't hesitate to contact us!

+

If you need anything else, don't hesitate to contact us at nijobs@aefeup.pt!


Sincerely,

NIJobs team at NIAEFEUP

\ No newline at end of file diff --git a/src/email-templates/confirm-application.handlebars b/src/email-templates/confirm-application.handlebars index 3924bd9f..8b55a041 100644 --- a/src/email-templates/confirm-application.handlebars +++ b/src/email-templates/confirm-application.handlebars @@ -1,7 +1,7 @@

Confirm your NIJobs application

-

We have successfully received your application!

-

Please follow this link to finish the process. Note that the link will expire in 10 minutes.

+

We have received your application successfully!

+

To complete the process, please click on the following link. Kindly note that the link will expire in 10 minutes.


-

If you did not request this or need anything else, please contact us at nijobs@aefeup.pt!


+

If you did not make this request or require any further assistance, please reach out to us at nijobs@aefeup.pt!


Sincerely,

NIJobs team at NIAEFEUP

\ No newline at end of file diff --git a/src/email-templates/new_company_application_company.handlebars b/src/email-templates/new_company_application_company.handlebars index 4c03b7b8..9a6085e0 100644 --- a/src/email-templates/new_company_application_company.handlebars +++ b/src/email-templates/new_company_application_company.handlebars @@ -1,7 +1,9 @@

Your application has been validated!

-

We will now review your application, and in case you're approved, you will receive another email with further instructions in order to complete your registration.

-

Your Application ID is {{applicationId}} and you registered {{companyName}}

-

Once you're approved, you will receive an email, and then you can log into NIJobs! Do not forget your password, you will need it on the first login.

+

We will now review your application to determine the trustworthiness of your company. + In the meantime, you can complete your registration by logging into your account and begin creating offers. + Please note that your offers will remain hidden from the public until your company is approved.

+

Your Application ID is {{applicationId}} and you registered {{companyName}}.

+

Once you are approved, you will receive an email notification, and your offers will become visible to the public.


If you did not request this or if you need anything else, don't hesitate to contact us at nijobs@aefeup.pt!


diff --git a/src/services/application.js b/src/services/application.js index 04e1a37f..505d0169 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -179,8 +179,13 @@ class CompanyApplicationService { if (!application) throw new CompanyApplicationNotFound(CompanyApplicationRules.MUST_EXIST_TO_APPROVE.msg); try { application.approve(); + await EmailService.sendMail({ + to: application.email, + ...APPROVAL_NOTIFICATION(application.companyName), + }); } catch (e) { - console.error(e); + console.error("Error while approving company ", e); + application.undoApproval(); throw new CompanyApplicationAlreadyReviewed(CompanyApplicationRules.CANNOT_REVIEW_TWICE.msg); } return Account.findOne({ email: application.email }); @@ -242,17 +247,10 @@ class CompanyApplicationService { try { const account = await (new AccountService()).registerCompany(application.email, application.password, application.companyName); - - await EmailService.sendMail({ - to: application.email, - ...APPROVAL_NOTIFICATION(application.companyName), - }); - return { application, account }; } catch (err) { - console.error(`Error creating account for approved Company Application, rolling back approval of ${application._id}`, err); - application.undoApproval(); + console.error(`Error creating account for validated Company Application`, err); if (err.name === "MongoServerError" && /E11000\s.*collection:\s.*\.accounts.*/.test(err.errmsg)) { throw new CompanyApplicationEmailAlreadyInUse(CompanyApplicationRules.EMAIL_ALREADY_IN_USE.msg); } else { From b12205c49beb6622aa1cb3e4c0e07c09afee8922 Mon Sep 17 00:00:00 2001 From: FranciscoCardoso913 Date: Sat, 15 Jul 2023 11:28:10 +0100 Subject: [PATCH 18/30] Adding and correcting tests for the endpoint apply/company Co-authored-by: Daniel Ferreira --- .env | 2 +- package-lock.json | 277 ++++++++---------- package.json | 1 + src/api/middleware/auth.js | 1 - src/api/routes/application.js | 6 +- src/api/routes/offer.js | 2 +- .../companyApplicationConfirmation.js | 5 - src/models/Offer.js | 4 +- src/services/application.js | 6 +- test/end-to-end/apply/company/index.js | 235 +++++++++++++++ test/end-to-end/auth.js | 2 +- 11 files changed, 370 insertions(+), 171 deletions(-) delete mode 100644 src/email-templates/companyApplicationConfirmation.js create mode 100644 test/end-to-end/apply/company/index.js diff --git a/.env b/.env index b11bd6b5..b86458d7 100644 --- a/.env +++ b/.env @@ -21,7 +21,7 @@ JWT_SECRET=Lendas contam que o Rui foi membro do IEEE. PASSWORD_RECOVERY_LINK=https://localhost:3000/recover # Frontend Application Confirmation Base Route -APPLICATION_CONFIRMATION_LINK=https://localhost:3000/apply/validate/ +APPLICATION_CONFIRMATION_LINK=https://localhost:3000/apply/ # Specifies the port in which the app will be exposed PORT=8087 diff --git a/package-lock.json b/package-lock.json index 276254f8..82755ce3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "bcrypt": "^5.1.0", "cloudinary": "^1.32.0", "dotenv-flow": "^3.2.0", + "expect": "^29.5.0", "express": "^4.18.2", "express-rate-limit": "^6.7.0", "express-session": "^1.17.3", @@ -2875,11 +2876,11 @@ } }, "node_modules/@jest/expect-utils": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", + "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", "dependencies": { - "jest-get-type": "^29.2.0" + "jest-get-type": "^29.4.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2958,11 +2959,11 @@ } }, "node_modules/@jest/schemas": { - "version": "29.0.0", - "dev": true, - "license": "MIT", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", + "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", "dependencies": { - "@sinclair/typebox": "^0.24.1" + "@sinclair/typebox": "^0.25.16" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3040,11 +3041,11 @@ "license": "MIT" }, "node_modules/@jest/types": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", + "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", "dependencies": { - "@jest/schemas": "^29.0.0", + "@jest/schemas": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -3156,9 +3157,9 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.24.51", - "dev": true, - "license": "MIT" + "version": "0.25.24", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", + "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==" }, "node_modules/@sinonjs/commons": { "version": "1.8.6", @@ -3231,12 +3232,10 @@ }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", - "dev": true, "license": "MIT" }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.0", - "dev": true, "license": "MIT", "dependencies": { "@types/istanbul-lib-coverage": "*" @@ -3244,7 +3243,6 @@ }, "node_modules/@types/istanbul-reports": { "version": "3.0.1", - "dev": true, "license": "MIT", "dependencies": { "@types/istanbul-lib-report": "*" @@ -3271,7 +3269,6 @@ }, "node_modules/@types/stack-utils": { "version": "2.0.1", - "dev": true, "license": "MIT" }, "node_modules/@types/webidl-conversions": { @@ -3288,7 +3285,6 @@ }, "node_modules/@types/yargs": { "version": "17.0.17", - "dev": true, "license": "MIT", "dependencies": { "@types/yargs-parser": "*" @@ -3296,7 +3292,6 @@ }, "node_modules/@types/yargs-parser": { "version": "21.0.0", - "dev": true, "license": "MIT" }, "node_modules/abbrev": { @@ -3779,7 +3774,6 @@ }, "node_modules/braces": { "version": "3.0.2", - "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.0.1" @@ -3918,7 +3912,6 @@ }, "node_modules/chalk": { "version": "4.1.0", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -3933,7 +3926,6 @@ }, "node_modules/chalk/node_modules/ansi-styles": { "version": "4.3.0", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -3947,7 +3939,6 @@ }, "node_modules/chalk/node_modules/color-convert": { "version": "2.0.1", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -3958,12 +3949,10 @@ }, "node_modules/chalk/node_modules/color-name": { "version": "1.1.4", - "dev": true, "license": "MIT" }, "node_modules/chalk/node_modules/has-flag": { "version": "4.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3971,7 +3960,6 @@ }, "node_modules/chalk/node_modules/supports-color": { "version": "7.2.0", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -4023,7 +4011,6 @@ }, "node_modules/ci-info": { "version": "3.7.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4429,9 +4416,9 @@ } }, "node_modules/diff-sequences": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", + "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -4954,15 +4941,15 @@ } }, "node_modules/expect": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", "dependencies": { - "@jest/expect-utils": "^29.3.1", - "jest-get-type": "^29.2.0", - "jest-matcher-utils": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1" + "@jest/expect-utils": "^29.5.0", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -5223,7 +5210,6 @@ }, "node_modules/fill-range": { "version": "7.0.1", - "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -5909,7 +5895,6 @@ }, "node_modules/is-number": { "version": "7.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -6191,14 +6176,14 @@ } }, "node_modules/jest-diff": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", + "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "diff-sequences": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -6247,9 +6232,9 @@ } }, "node_modules/jest-get-type": { - "version": "29.2.0", - "dev": true, - "license": "MIT", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -6291,31 +6276,31 @@ } }, "node_modules/jest-matcher-utils": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", + "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "jest-diff": "^29.5.0", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", + "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.3.1", + "@jest/types": "^29.5.0", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.3.1", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -6503,11 +6488,11 @@ } }, "node_modules/jest-util": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", + "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", "dependencies": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -6865,7 +6850,6 @@ }, "node_modules/micromatch": { "version": "4.0.5", - "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.2", @@ -7670,7 +7654,6 @@ }, "node_modules/picomatch": { "version": "2.3.1", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -7707,11 +7690,11 @@ } }, "node_modules/pretty-format": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", "dependencies": { - "@jest/schemas": "^29.0.0", + "@jest/schemas": "^29.4.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -7721,7 +7704,6 @@ }, "node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -7899,7 +7881,6 @@ }, "node_modules/react-is": { "version": "18.2.0", - "dev": true, "license": "MIT" }, "node_modules/readable-stream": { @@ -8260,7 +8241,6 @@ }, "node_modules/slash": { "version": "3.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -8350,7 +8330,6 @@ }, "node_modules/stack-utils": { "version": "2.0.6", - "dev": true, "license": "MIT", "dependencies": { "escape-string-regexp": "^2.0.0" @@ -8361,7 +8340,6 @@ }, "node_modules/stack-utils/node_modules/escape-string-regexp": { "version": "2.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -8604,7 +8582,6 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", - "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -10928,10 +10905,11 @@ } }, "@jest/expect-utils": { - "version": "29.3.1", - "dev": true, + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", + "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", "requires": { - "jest-get-type": "^29.2.0" + "jest-get-type": "^29.4.3" } }, "@jest/fake-timers": { @@ -10987,10 +10965,11 @@ } }, "@jest/schemas": { - "version": "29.0.0", - "dev": true, + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", + "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", "requires": { - "@sinclair/typebox": "^0.24.1" + "@sinclair/typebox": "^0.25.16" } }, "@jest/source-map": { @@ -11050,10 +11029,11 @@ } }, "@jest/types": { - "version": "29.3.1", - "dev": true, + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", + "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", "requires": { - "@jest/schemas": "^29.0.0", + "@jest/schemas": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -11127,8 +11107,9 @@ } }, "@sinclair/typebox": { - "version": "0.24.51", - "dev": true + "version": "0.25.24", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", + "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==" }, "@sinonjs/commons": { "version": "1.8.6", @@ -11189,19 +11170,16 @@ } }, "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "dev": true + "version": "2.0.4" }, "@types/istanbul-lib-report": { "version": "3.0.0", - "dev": true, "requires": { "@types/istanbul-lib-coverage": "*" } }, "@types/istanbul-reports": { "version": "3.0.1", - "dev": true, "requires": { "@types/istanbul-lib-report": "*" } @@ -11224,8 +11202,7 @@ "dev": true }, "@types/stack-utils": { - "version": "2.0.1", - "dev": true + "version": "2.0.1" }, "@types/webidl-conversions": { "version": "7.0.0" @@ -11239,14 +11216,12 @@ }, "@types/yargs": { "version": "17.0.17", - "dev": true, "requires": { "@types/yargs-parser": "*" } }, "@types/yargs-parser": { - "version": "21.0.0", - "dev": true + "version": "21.0.0" }, "abbrev": { "version": "1.1.1" @@ -11557,7 +11532,6 @@ }, "braces": { "version": "3.0.2", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -11623,7 +11597,6 @@ }, "chalk": { "version": "4.1.0", - "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -11631,29 +11604,24 @@ "dependencies": { "ansi-styles": { "version": "4.3.0", - "dev": true, "requires": { "color-convert": "^2.0.1" } }, "color-convert": { "version": "2.0.1", - "dev": true, "requires": { "color-name": "~1.1.4" } }, "color-name": { - "version": "1.1.4", - "dev": true + "version": "1.1.4" }, "has-flag": { - "version": "4.0.0", - "dev": true + "version": "4.0.0" }, "supports-color": { "version": "7.2.0", - "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -11682,8 +11650,7 @@ "version": "2.0.0" }, "ci-info": { - "version": "3.7.0", - "dev": true + "version": "3.7.0" }, "cjs-module-lexer": { "version": "1.2.2", @@ -11927,8 +11894,9 @@ } }, "diff-sequences": { - "version": "29.3.1", - "dev": true + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", + "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==" }, "doctrine": { "version": "3.0.0", @@ -12238,14 +12206,15 @@ "dev": true }, "expect": { - "version": "29.3.1", - "dev": true, + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", "requires": { - "@jest/expect-utils": "^29.3.1", - "jest-get-type": "^29.2.0", - "jest-matcher-utils": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1" + "@jest/expect-utils": "^29.5.0", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0" } }, "express": { @@ -12416,7 +12385,6 @@ }, "fill-range": { "version": "7.0.1", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -12834,8 +12802,7 @@ } }, "is-number": { - "version": "7.0.0", - "dev": true + "version": "7.0.0" }, "is-path-inside": { "version": "3.0.3", @@ -13011,13 +12978,14 @@ } }, "jest-diff": { - "version": "29.3.1", - "dev": true, + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", + "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", "requires": { "chalk": "^4.0.0", - "diff-sequences": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "diff-sequences": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" } }, "jest-docblock": { @@ -13051,8 +13019,9 @@ } }, "jest-get-type": { - "version": "29.2.0", - "dev": true + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==" }, "jest-haste-map": { "version": "29.3.1", @@ -13081,26 +13050,28 @@ } }, "jest-matcher-utils": { - "version": "29.3.1", - "dev": true, + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", + "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "jest-diff": "^29.5.0", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" } }, "jest-message-util": { - "version": "29.3.1", - "dev": true, + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", + "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.3.1", + "@jest/types": "^29.5.0", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.3.1", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } @@ -13241,10 +13212,11 @@ } }, "jest-util": { - "version": "29.3.1", - "dev": true, + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", + "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", "requires": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -13485,7 +13457,6 @@ }, "micromatch": { "version": "4.0.5", - "dev": true, "requires": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -13971,8 +13942,7 @@ "version": "1.0.0" }, "picomatch": { - "version": "2.3.1", - "dev": true + "version": "2.3.1" }, "pirates": { "version": "4.0.5", @@ -13990,17 +13960,17 @@ "dev": true }, "pretty-format": { - "version": "29.3.1", - "dev": true, + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", "requires": { - "@jest/schemas": "^29.0.0", + "@jest/schemas": "^29.4.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "dependencies": { "ansi-styles": { - "version": "5.2.0", - "dev": true + "version": "5.2.0" } } }, @@ -14104,8 +14074,7 @@ } }, "react-is": { - "version": "18.2.0", - "dev": true + "version": "18.2.0" }, "readable-stream": { "version": "2.3.7", @@ -14341,8 +14310,7 @@ "dev": true }, "slash": { - "version": "3.0.0", - "dev": true + "version": "3.0.0" }, "smart-buffer": { "version": "4.2.0" @@ -14401,14 +14369,12 @@ }, "stack-utils": { "version": "2.0.6", - "dev": true, "requires": { "escape-string-regexp": "^2.0.0" }, "dependencies": { "escape-string-regexp": { - "version": "2.0.0", - "dev": true + "version": "2.0.0" } } }, @@ -14554,7 +14520,6 @@ }, "to-regex-range": { "version": "5.0.1", - "dev": true, "requires": { "is-number": "^7.0.0" } diff --git a/package.json b/package.json index dd3783a2..4c721477 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "bcrypt": "^5.1.0", "cloudinary": "^1.32.0", "dotenv-flow": "^3.2.0", + "expect": "^29.5.0", "express": "^4.18.2", "express-rate-limit": "^6.7.0", "express-session": "^1.17.3", diff --git a/src/api/middleware/auth.js b/src/api/middleware/auth.js index ffc69e6d..001d8765 100644 --- a/src/api/middleware/auth.js +++ b/src/api/middleware/auth.js @@ -87,7 +87,6 @@ export const validToken = (req, res, next) => { return next(); } catch (jwtErr) { - console.log(jwtErr); if (jwtErr.name === "TokenExpiredError") { return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.EXPIRED_TOKEN)); } else { diff --git a/src/api/routes/application.js b/src/api/routes/application.js index 2c22a98b..efaf0508 100644 --- a/src/api/routes/application.js +++ b/src/api/routes/application.js @@ -26,7 +26,11 @@ export default (app) => { return next(err); } }); - router.post("/validate/:token/confirm", validators.finishValidation, validToken, async (req, res, next) => { + + /** + * Validates application + */ + router.post("/:token/validate", validators.finishValidation, validToken, async (req, res, next) => { const { _id: id } = req.locals.token; try { await new ApplicationService().applicationValidation(id); diff --git a/src/api/routes/offer.js b/src/api/routes/offer.js index ff87ec9d..252d6b8c 100644 --- a/src/api/routes/offer.js +++ b/src/api/routes/offer.js @@ -106,7 +106,7 @@ export default (app) => { const params = { ...req.body, owner: req.targetOwner, - isPending: !(application.state === ApplicationStatus.APPROVED), + isPending: application.state !== ApplicationStatus.APPROVED, }; const offer = await (new OfferService()).create(params); return res.json(offer); diff --git a/src/email-templates/companyApplicationConfirmation.js b/src/email-templates/companyApplicationConfirmation.js deleted file mode 100644 index 7745145c..00000000 --- a/src/email-templates/companyApplicationConfirmation.js +++ /dev/null @@ -1,5 +0,0 @@ -export const APPLICATION_CONFIRMATION = (link) => ({ - subject: "Confirm your NIJobs application", - template: "confirm-application", - context: { link }, -}); diff --git a/src/models/Offer.js b/src/models/Offer.js index 573b2ae8..51645b3f 100644 --- a/src/models/Offer.js +++ b/src/models/Offer.js @@ -165,9 +165,9 @@ OfferSchema.query.current = function() { return this.where(this.model.filterCurrent()); }; -OfferSchema.query.notPending= function(){ +OfferSchema.query.notPending = function() { return this.where({ isPending: false }); -} +}; /** * Currently active and non-hidden Offers diff --git a/src/services/application.js b/src/services/application.js index 505d0169..83eb95ed 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -2,7 +2,6 @@ import CompanyApplication, { CompanyApplicationRules } from "../models/CompanyAp import { generateToken } from "../lib/token.js"; import hash from "../lib/passwordHashing.js"; import { VALIDATION_LINK_EXPIRATION } from "../models/constants/ApplicationStatus.js"; -import { APPLICATION_CONFIRMATION } from "../email-templates/companyApplicationConfirmation.js"; import AccountService from "./account.js"; import EmailService from "../lib/emailService.js"; import { @@ -10,6 +9,7 @@ import { NEW_COMPANY_APPLICATION_COMPANY, APPROVAL_NOTIFICATION, REJECTION_NOTIFICATION, + APPLICATION_CONFIRMATION } from "../email-templates/companyApplicationApproval.js"; import config from "../config/env.js"; import Account from "../models/Account.js"; @@ -211,7 +211,7 @@ class CompanyApplicationService { buildConfirmationLink(id) { const token = generateToken({ _id: id }, config.jwt_secret, VALIDATION_LINK_EXPIRATION); - return `${config.application_confirmation_link}${token}/confirm`; + return `${config.application_confirmation_link}${token}/validate`; } async sendConfirmationNotification(email, link) { @@ -250,7 +250,7 @@ class CompanyApplicationService { return { application, account }; } catch (err) { - console.error(`Error creating account for validated Company Application`, err); + console.error("Error creating account for validated Company Application", err); if (err.name === "MongoServerError" && /E11000\s.*collection:\s.*\.accounts.*/.test(err.errmsg)) { throw new CompanyApplicationEmailAlreadyInUse(CompanyApplicationRules.EMAIL_ALREADY_IN_USE.msg); } else { diff --git a/test/end-to-end/apply/company/index.js b/test/end-to-end/apply/company/index.js new file mode 100644 index 00000000..9afb627c --- /dev/null +++ b/test/end-to-end/apply/company/index.js @@ -0,0 +1,235 @@ +import EmailService from "../../../../src/lib/emailService"; +import { StatusCodes } from "http-status-codes"; +import CompanyApplication, { CompanyApplicationRules } from "../../../../src/models/CompanyApplication"; +import Account from "../../../../src/models/Account"; +import ValidatorTester from "../../../utils/ValidatorTester"; +import ValidationReasons from "../../../../src/api/middleware/validators/validationReasons"; +import CompanyApplicationConstants from "../../../../src/models/constants/CompanyApplication"; +import AccountConstants from "../../../../src/models/constants/Account"; +import CompanyConstants from "../../../../src/models/constants/Company"; +import { APPLICATION_CONFIRMATION } + from "../../../../src/email-templates/companyApplicationApproval"; +import config from "../../../../src/config/env"; +import * as token from "../../../../src/lib/token.js"; +import env from "../../../../src/config/env.js"; +import { VALIDATION_LINK_EXPIRATION } from "../../../../src/models/constants/ApplicationStatus.js"; +import mongoose from "mongoose"; +import { SECOND_IN_MS } from "../../../../src/models/constants/TimeConstants.js"; +const generateTokenSpy = jest.spyOn(token, "generateToken"); +jest.spyOn(token, "verifyAndDecodeToken"); + +describe("POST /apply/company", () => { + describe("Input Validation", () => { + const EndpointValidatorTester = ValidatorTester((params) => request().post("/apply/company").send(params)); + const BodyValidatorTester = EndpointValidatorTester("body"); + + describe("email", () => { + const FieldValidatorTester = BodyValidatorTester("email"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustBeEmail(); + }); + + describe("password", () => { + const FieldValidatorTester = BodyValidatorTester("password"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustBeString(); + FieldValidatorTester.hasMinLength(AccountConstants.password.min_length); + FieldValidatorTester.hasNumber(); + }); + + describe("motivation", () => { + const FieldValidatorTester = BodyValidatorTester("motivation"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustBeString(); + FieldValidatorTester.hasMinLength(CompanyApplicationConstants.motivation.min_length); + FieldValidatorTester.hasMaxLength(CompanyApplicationConstants.motivation.max_length); + }); + + describe("companyName", () => { + const FieldValidatorTester = BodyValidatorTester("companyName"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustBeString(); + FieldValidatorTester.hasMinLength(CompanyConstants.companyName.min_length); + FieldValidatorTester.hasMaxLength(CompanyConstants.companyName.max_length); + }); + }); + + describe("Without any existing application and accounts", () => { + + const RealDateNow = Date.now; + const mockCurrentDate = new Date("2019-11-23"); + + beforeAll(async () => { + await CompanyApplication.deleteMany({}); + await Account.deleteMany({}); + + Date.now = () => mockCurrentDate.getTime(); + }); + + afterAll(async () => { + await CompanyApplication.deleteMany({}); + await Account.deleteMany({}); + + Date.now = RealDateNow; + }); + + test("Valid creation", async () => { + const application = { + email: "test@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation because otherwise, the tests would not exist.", + }; + const res = await request() + .post("/apply/company") + .send(application) + .expect(StatusCodes.OK); + + // eslint-disable-next-line no-unused-vars + const { password, ...rest } = application; + expect(res.body).toMatchObject(rest); + }); + + test("Should send an email to company user after creating application", async () => { + const application = { + email: "test2@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation because otherwise, the tests would not exist.", + }; + + const res = await request() + .post("/apply/company") + .send(application) + .expect(StatusCodes.OK); + + expect(token.generateToken).toHaveBeenCalledWith( + { _id: mongoose.Types.ObjectId(res.body.id) }, env.jwt_secret, VALIDATION_LINK_EXPIRATION + ); + + const generatedToken = generateTokenSpy.mock.results[0].value; + + const companyEmailOptions = APPLICATION_CONFIRMATION( + `${config.application_confirmation_link}${generatedToken}/validate` + ); + + expect(EmailService.sendMail).toHaveBeenCalledWith(expect.objectContaining({ + subject: companyEmailOptions.subject, + to: application.email, + template: companyEmailOptions.template, + context: { ...companyEmailOptions.context }, + })); + }); + + test("Should replace application if new one is created after 10 minutes", async () => { + const application = { + email: "test3@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", + }; + + const res1 = await request() + .post("/apply/company") + .send(application) + .expect(StatusCodes.OK); + + const TempRealDate = Date.now; + const tenMinAfter = new Date(Date.now() + (VALIDATION_LINK_EXPIRATION * SECOND_IN_MS)); + Date.now = () => tenMinAfter.getTime(); + + const res2 = await request() + .post("/apply/company") + .send(application) + .expect(StatusCodes.OK); + + expect(await CompanyApplication.findOne({ _id: res1.body._id })).toBeFalsy(); + expect(await CompanyApplication.findOne({ _id: res2.body._id })).toBeTruthy(); + + Date.now = TempRealDate; + }); + + + describe("Invalid input", () => { + + const application = { + email: "test2@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", + }; + + beforeAll(async () => { + await Account.deleteMany({}); + await CompanyApplication.deleteMany({}); + }); + + afterAll(async () => { + await Account.deleteMany({}); + await CompanyApplication.deleteMany({}); + }); + + test("Should fail while using an email with an associated Account", async () => { + + await Account.create({ + email: application.email, + password: application.password, + isAdmin: true, + }); + + const res = await request() + .post("/apply/company") + .send(application) + .expect(StatusCodes.UNPROCESSABLE_ENTITY); + + expect(res.body.errors).toContainEqual({ + "location": "body", + "msg": ValidationReasons.ALREADY_EXISTS("email"), + "param": "email", + "value": application.email, + }); + }); + + test("Should fail while using an email with an associated application that was not rejected", async () => { + + // Guarantees that the company application will succeed regarding account rules + await Account.deleteOne({ email: application.email }); + + // Existing Application - Default `Pending` state + await CompanyApplication.create({ + ...application, + submittedAt: Date.now(), + }); + + const res = await request() + .post("/apply/company") + .send(application) + .expect(StatusCodes.UNPROCESSABLE_ENTITY); + + expect(res.body.errors).toContainEqual({ + "location": "body", + "msg": CompanyApplicationRules.ONLY_ONE_APPLICATION_ACTIVE_PER_EMAIL.msg, + "param": "email", + "value": application.email, + }); + }); + test("Should fail while using an email associated with an unverified application 10 minutes before its creation", async () => { + await Account.deleteMany({}); + await CompanyApplication.deleteMany({}); + await request() + .post("/apply/company") + .send(application) + .expect(StatusCodes.OK); + + const res = await request() + .post("/apply/company") + .send(application) + .expect(StatusCodes.FORBIDDEN); + + expect(res.body.errors).toContainEqual({ + "msg": CompanyApplicationRules.APPLICATION_RECENTLY_CREATED.msg, + }); + }); + }); + }); +}); diff --git a/test/end-to-end/auth.js b/test/end-to-end/auth.js index 3d005b60..d98dbe81 100644 --- a/test/end-to-end/auth.js +++ b/test/end-to-end/auth.js @@ -175,7 +175,7 @@ describe("Login endpoint test", () => { expect(res.body).not.toHaveProperty("data.company"); }); - test("should return the informations of the logged in user (company)", async () => { + test("should return the information of the logged in user (company)", async () => { await test_agent .post("/auth/login") .send(test_user_company); From 6dada6d85639f7d13f2e360e35c37154fec8383c Mon Sep 17 00:00:00 2001 From: FranciscoCardoso913 Date: Sat, 15 Jul 2023 15:15:26 +0100 Subject: [PATCH 19/30] Adding tests for the endpoint apply/company/:token/validate and changing the type of errors some functions throw Co-authored-by: Daniel Ferreira --- src/api/middleware/auth.js | 4 +- src/services/account.js | 7 +- src/services/application.js | 6 +- .../apply/company/:token/validate.js | 135 ++++++++++++++++++ 4 files changed, 140 insertions(+), 12 deletions(-) create mode 100644 test/end-to-end/apply/company/:token/validate.js diff --git a/src/api/middleware/auth.js b/src/api/middleware/auth.js index 001d8765..aed1656a 100644 --- a/src/api/middleware/auth.js +++ b/src/api/middleware/auth.js @@ -88,9 +88,9 @@ export const validToken = (req, res, next) => { return next(); } catch (jwtErr) { if (jwtErr.name === "TokenExpiredError") { - return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.EXPIRED_TOKEN)); + return next(new APIError(HTTPStatus.GONE, ErrorTypes.FORBIDDEN, ValidationReasons.EXPIRED_TOKEN)); } else { - return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.INVALID_TOKEN)); + return next(new APIError(HTTPStatus.NOT_FOUND, ErrorTypes.FORBIDDEN, ValidationReasons.INVALID_TOKEN)); } } }; diff --git a/src/services/account.js b/src/services/account.js index bb9572bb..b66ef251 100644 --- a/src/services/account.js +++ b/src/services/account.js @@ -29,16 +29,11 @@ class AccountService { const company = await Company.create({ name: companyName }); - const account = await Account.create({ + await Account.create({ email, password, company, }); - - return { - email: account.email, - companyName: account.company.name, - }; } async updatePassword(email, password) { diff --git a/src/services/application.js b/src/services/application.js index 83eb95ed..f80946db 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -246,12 +246,10 @@ class CompanyApplicationService { } try { - const account = await (new AccountService()).registerCompany(application.email, application.password, application.companyName); - return { application, account }; - + await (new AccountService()).registerCompany(application.email, application.password, application.companyName); } catch (err) { console.error("Error creating account for validated Company Application", err); - if (err.name === "MongoServerError" && /E11000\s.*collection:\s.*\.accounts.*/.test(err.errmsg)) { + if (err.name === "MongoServerError" && /E11000\s.*collection:\s.*\.accounts.*/.test(err.msg)) { throw new CompanyApplicationEmailAlreadyInUse(CompanyApplicationRules.EMAIL_ALREADY_IN_USE.msg); } else { throw err; diff --git a/test/end-to-end/apply/company/:token/validate.js b/test/end-to-end/apply/company/:token/validate.js new file mode 100644 index 00000000..4633a7f4 --- /dev/null +++ b/test/end-to-end/apply/company/:token/validate.js @@ -0,0 +1,135 @@ +import EmailService from "../../../../../src/lib/emailService"; +import { StatusCodes } from "http-status-codes"; +import CompanyApplication from "../../../../../src/models/CompanyApplication.js"; +import Account from "../../../../../src/models/Account.js"; +import { NEW_COMPANY_APPLICATION_ADMINS, NEW_COMPANY_APPLICATION_COMPANY } + from "../../../../../src/email-templates/companyApplicationApproval"; +import config from "../../../../../src/config/env"; +import * as token from "../../../../../src/lib/token.js"; +import Company from "../../../../../src/models/Company"; +import { VALIDATION_LINK_EXPIRATION } from "../../../../../src/models/constants/ApplicationStatus.js"; +import { SECOND_IN_MS } from "../../../../../src/models/constants/TimeConstants.js"; +const generateTokenSpy = jest.spyOn(token, "generateToken"); +jest.spyOn(token, "verifyAndDecodeToken"); + +describe("POST /apply/company/:token/validate", () => { + + describe("Validating application", () => { + const application = { + email: "test@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation because otherwise, the tests would not exist.", + }; + + beforeAll(async () => { + await CompanyApplication.deleteMany({}); + await Account.deleteMany({}); + }); + + afterEach(async () => { + await CompanyApplication.deleteMany({}); + await Account.deleteMany({}); + await Company.deleteMany({}); + }); + + test("Should validate application and create its account and company", async () => { + await request() + .post("/apply/company") + .send(application) + .expect(StatusCodes.OK); + + const generatedToken = generateTokenSpy.mock.results[0].value; + + await request() + .post(`/apply/company/${generatedToken}/validate`) + .expect(StatusCodes.OK); + + const applicationUpdated = await CompanyApplication.findOne({ application }); + const account = await Account.findOne({ email: application.email }); + + expect(account).not.toBeNull(); + expect(Company.findOne({ _id: account.company })).toBeTruthy(); + expect(applicationUpdated.state).toBe("PENDING"); + }); + + test("Should send an email to the company and one to the NIJobs team", async () => { + const res = await request() + .post("/apply/company") + .send(application) + .expect(StatusCodes.OK); + + const generatedToken = generateTokenSpy.mock.results[0].value; + + await request() + .post(`/apply/company/${generatedToken}/validate`) + .expect(StatusCodes.OK); + + const adminEmailOptions = NEW_COMPANY_APPLICATION_ADMINS( + application.email, + application.companyName, + application.motivation + ); + + const companyEmailOptions = NEW_COMPANY_APPLICATION_COMPANY( + application.companyName, + res.body._id + ); + + expect(EmailService.sendMail).toHaveBeenNthCalledWith(2, expect.objectContaining({ + subject: adminEmailOptions.subject, + to: config.mail_from, + template: adminEmailOptions.template, + context: { ...adminEmailOptions.context }, + })); + + expect(EmailService.sendMail).toHaveBeenNthCalledWith(3, expect.objectContaining({ + subject: companyEmailOptions.subject, + to: application.email, + template: companyEmailOptions.template, + context: { ...companyEmailOptions.context }, + })); + }); + + test("Should fail if application is already validated", async () => { + await request() + .post("/apply/company") + .send(application) + .expect(StatusCodes.OK); + + const generatedToken = generateTokenSpy.mock.results[0].value; + + await request() + .post(`/apply/company/${generatedToken}/validate`) + .expect(StatusCodes.OK); + + await request() + .post(`/apply/company/${generatedToken}/validate`) + .expect(StatusCodes.CONFLICT); + }); + + test("Should fail if token does not exist", async () => { + await request() + .post(`/apply/company/${0}/validate`) + .expect(StatusCodes.NOT_FOUND); + + }); + + test("Should fail if link has expired", async () => { + await request() + .post("/apply/company") + .send(application) + .expect(StatusCodes.OK); + + const generatedToken = generateTokenSpy.mock.results[0].value; + const RealDateNow = Date.now; + const mockCurrentDate = new Date(Date.now() + (VALIDATION_LINK_EXPIRATION * SECOND_IN_MS)); + Date.now = () => mockCurrentDate; + await request() + .post(`/apply/company/${generatedToken}/validate`) + .expect(StatusCodes.GONE); + + Date.now = RealDateNow; + }); + }); +}); From 3f60be84c037ee17b37484649e367bd0b3605368 Mon Sep 17 00:00:00 2001 From: FranciscoCardoso913 Date: Thu, 20 Jul 2023 18:57:49 +0100 Subject: [PATCH 20/30] Adding tests for the endpoint /company/:companyId/state Co-authored-by: Daniel Ferreira --- src/api/routes/company.js | 7 +- src/services/account.js | 2 +- test/end-to-end/auth.js | 5 +- test/end-to-end/company/:companyId/state.js | 161 ++++++++++++++++++++ 4 files changed, 167 insertions(+), 8 deletions(-) create mode 100644 test/end-to-end/company/:companyId/state.js diff --git a/src/api/routes/company.js b/src/api/routes/company.js index cb565f56..6407cf58 100644 --- a/src/api/routes/company.js +++ b/src/api/routes/company.js @@ -258,9 +258,9 @@ export default (app) => { ); /** - * Get the application of a company + * Get the state of a company with its id */ - router.get("/:companyId/application", + router.get("/:companyId/state", or([ authMiddleware.isAdmin, authMiddleware.isGod, @@ -268,13 +268,12 @@ export default (app) => { ], { status_code: HTTPStatus.UNAUTHORIZED, error_code: ErrorTypes.FORBIDDEN, msg: ValidationReasons.INSUFFICIENT_PERMISSIONS }), validators.getApplication, - async (req, res, next) => { try { const account = await Account.findOne({ "company": req.params.companyId }); const application = await CompanyApplication.findOne({ "email": account.email }); - return res.json(application); + return res.json(application.state); } catch (err) { console.error(err); return next(err); diff --git a/src/services/account.js b/src/services/account.js index b66ef251..caeaae1d 100644 --- a/src/services/account.js +++ b/src/services/account.js @@ -31,7 +31,7 @@ class AccountService { await Account.create({ email, - password, + password: await hash(password), company, }); } diff --git a/test/end-to-end/auth.js b/test/end-to-end/auth.js index d98dbe81..d19c1320 100644 --- a/test/end-to-end/auth.js +++ b/test/end-to-end/auth.js @@ -145,7 +145,6 @@ describe("Login endpoint test", () => { email: "user@gmail.com", password: "password", }); - expect(res.status).toBe(HTTPStatus.UNAUTHORIZED); }); @@ -159,7 +158,7 @@ describe("Login endpoint test", () => { expect(res.status).toBe(HTTPStatus.OK); }); - test("should return the informations of the logged in user (admin)", async () => { + test("should return the information of the logged in user (admin)", async () => { await test_agent .post("/auth/login") @@ -192,7 +191,7 @@ describe("Login endpoint test", () => { )); }); - test("should be successful when loging out the current user", async () => { + test("should be successful when logging out the current user", async () => { const res = await test_agent .delete("/auth/login") .send(); diff --git a/test/end-to-end/company/:companyId/state.js b/test/end-to-end/company/:companyId/state.js new file mode 100644 index 00000000..64aaac32 --- /dev/null +++ b/test/end-to-end/company/:companyId/state.js @@ -0,0 +1,161 @@ +import { StatusCodes } from "http-status-codes"; +import CompanyApplication from "../../../../src/models/CompanyApplication"; +import Account from "../../../../src/models/Account"; +import * as token from "../../../../src/lib/token.js"; +import Company from "../../../../src/models/Company.js"; +import AccountService from "../../../../src/services/account.js"; +import CompanyApplicationService from "../../../../src/services/application.js"; +import withGodToken from "../../../utils/GodToken.js"; + +describe("GET /company/:companyId/state", () => { + const test_agent = agent(); + + let companyId; + + const test_user_company1 = { + email: "company1@email.com", + password: "password123", + }; + + describe("Testing permissions", () => { + + const test_user_admin = { + email: "admin@email.com", + password: "password123", + }; + + const test_user_company2 = { + email: "company2@email.com", + password: "password123", + }; + + beforeAll(async () => { + await Account.deleteMany({}); + await Company.deleteMany({}); + await CompanyApplication.deleteMany({}); + await test_agent + .delete("/auth/login"); + const accountService = new AccountService(); + await (new CompanyApplicationService()).create({ + email: test_user_company1.email, + password: test_user_company1.password, + companyName: "test company", + motivation: "I want people for job :)" + }); + await accountService.registerAdmin(test_user_admin.email, test_user_admin.password); + await accountService.registerCompany(test_user_company1.email, test_user_company1.password, "test company"); + await accountService.registerCompany(test_user_company2.email, test_user_company2.password, "test company 2"); + + companyId = (await Company.findOne({ name: "test company" }))._id; + }); + + + afterEach(async () => { + await test_agent + .delete("/auth/login"); + }); + + afterAll(async () => { + await Account.deleteMany({}); + await Company.deleteMany({}); + await CompanyApplication.deleteMany({}); + }); + + test("Should succeed if the user is logged in an admin account", async () => { + await test_agent + .post("/auth/login") + .send(test_user_admin) + .expect(StatusCodes.OK); + + const res = await test_agent + .get(`/company/${companyId.toString()}/state`); + + expect(res.status).toBe(StatusCodes.OK); + }); + + test("Should succeed if the user is logged in a god account", async () => { + await test_agent.delete("/auth/login"); + await test_agent + .post("/auth/login") + .send(test_user_company1) + .expect(StatusCodes.OK); + + const res = await test_agent + .get(`/company/${companyId}/state`) + .send(withGodToken()); + + expect(res.status).toBe(StatusCodes.OK); + }); + + test("Should succeed if the user is logged in to its company account", async () => { + await test_agent + .post("/auth/login") + .send(test_user_company1) + .expect(StatusCodes.OK); + + const res = await test_agent + .get(`/company/${companyId}/state`); + + expect(res.status).toBe(StatusCodes.OK); + }); + + test("Should failed if the user is not logged in", async () => { + await test_agent + .get(`/company/${companyId}/state`).expect(StatusCodes.UNAUTHORIZED); + + }); + + test("Should fail if the user is logged in to an account without access to the company", async () => { + await test_agent + .post("/auth/login") + .send(test_user_company2) + .expect(StatusCodes.OK); + + await test_agent + .get(`/company/${companyId}/state`) + .expect(StatusCodes.UNAUTHORIZED); + }); + }); + + describe("Testing endpoint's result", () => { + let application; + + beforeAll(async () => { + await Account.deleteMany({}); + await Company.deleteMany({}); + await CompanyApplication.deleteMany({}); + await test_agent + .delete("/auth/login"); + const accountService = new AccountService(); + application = await (new CompanyApplicationService()).create({ + email: test_user_company1.email, + password: test_user_company1.password, + companyName: "test company", + motivation: "I want people for job :)" + }); + await accountService.registerCompany(test_user_company1.email, test_user_company1.password, "test company"); + + companyId = (await Company.findOne({ name: "test company" }))._id; + }); + + afterAll(async () => { + await Account.deleteMany({}); + await Company.deleteMany({}); + await CompanyApplication.deleteMany({}); + }); + + test("Should return the state of the application", async () => { + await test_agent + .post("/auth/login") + .send(test_user_company1) + .expect(StatusCodes.OK); + + const res = await test_agent + .get(`/company/${companyId}/state`) + .expect(StatusCodes.OK); + + expect(res.body).toBe(application.state); + }); + + }); +}); From 482b0155a014d5c874983907d1ad89efcd0213eb Mon Sep 17 00:00:00 2001 From: FranciscoCardoso913 Date: Sat, 29 Jul 2023 11:01:17 +0100 Subject: [PATCH 21/30] Created and fixed tests for the offers/ endpoint and fixed tests for the auth/recover/:token/confirm endpoint Co-authored-by: Daniel Ferreira --- .../validators/validationReasons.js | 2 +- test/end-to-end/application.js | 37 - test/end-to-end/auth.js | 12 +- .../end-to-end/auth/recover/:token/confirm.js | 188 ++ test/end-to-end/company/:companyId/state.js | 1 - test/end-to-end/offer.js | 16 + test/end-to-end/offers/index.js | 2145 +++++++++++++++++ test/end-to-end/offers/new.js | 1056 ++++++++ 8 files changed, 3412 insertions(+), 45 deletions(-) create mode 100644 test/end-to-end/auth/recover/:token/confirm.js create mode 100644 test/end-to-end/offers/index.js create mode 100644 test/end-to-end/offers/new.js diff --git a/src/api/middleware/validators/validationReasons.js b/src/api/middleware/validators/validationReasons.js index 62b884a8..99066a19 100644 --- a/src/api/middleware/validators/validationReasons.js +++ b/src/api/middleware/validators/validationReasons.js @@ -52,7 +52,7 @@ const ValidationReasons = Object.freeze({ NON_EXISTING_APPLICATION: "application-does-not-exist", FILE_TOO_LARGE: (max) => `file-cant-be-larger-than-${max}MB`, MUST_BE_GREATER_THAN_OR_EQUAL_TO: (field) => `must-be-greater-than-or-equal-to:${field}`, - APPLICATION_RECENTLY_CREATED: "application-created-in-less-than-five-minutes-ago", + }); export default ValidationReasons; diff --git a/test/end-to-end/application.js b/test/end-to-end/application.js index 28fb316f..37c4afab 100644 --- a/test/end-to-end/application.js +++ b/test/end-to-end/application.js @@ -1,4 +1,3 @@ -import EmailService from "../../src/lib/emailService"; import { StatusCodes as HTTPStatus } from "http-status-codes"; import CompanyApplication, { CompanyApplicationRules } from "../../src/models/CompanyApplication"; import Account from "../../src/models/Account"; @@ -7,9 +6,6 @@ import ValidationReasons from "../../src/api/middleware/validators/validationRea import CompanyApplicationConstants from "../../src/models/constants/CompanyApplication"; import AccountConstants from "../../src/models/constants/Account"; import CompanyConstants from "../../src/models/constants/Company"; -import { NEW_COMPANY_APPLICATION_ADMINS, NEW_COMPANY_APPLICATION_COMPANY } from "../../src/email-templates/companyApplicationApproval"; -import config from "../../src/config/env"; - describe("Company application endpoint test", () => { describe("POST /application", () => { @@ -87,39 +83,6 @@ describe("Company application endpoint test", () => { expect(created_application).toHaveProperty("submittedAt", mockCurrentDate); }); - test("Should send an email to admin and to company user", async () => { - const application = { - email: "test2@test.com", - password: "password123", - companyName: "Testing company", - motivation: "This company has a very valid motivation because otherwise, the tests would not exist.", - }; - const res = await request() - .post("/apply/company") - .send(application); - - expect(res.status).toBe(HTTPStatus.OK); - - const adminEmailOptions = NEW_COMPANY_APPLICATION_ADMINS( - application.email, application.companyName, application.motivation); - const companyEmailOptions = NEW_COMPANY_APPLICATION_COMPANY( - application.companyName, res.body._id); - - expect(EmailService.sendMail).toHaveBeenCalledWith(expect.objectContaining({ - subject: adminEmailOptions.subject, - to: config.mail_from, - template: adminEmailOptions.template, - context: adminEmailOptions.context, - })); - - expect(EmailService.sendMail).toHaveBeenCalledWith(expect.objectContaining({ - subject: companyEmailOptions.subject, - to: application.email, - template: companyEmailOptions.template, - context: { ...companyEmailOptions.context }, - })); - }); - describe("Invalid input", () => { test("Should fail while using an email with an associated Account", async () => { const application = { diff --git a/test/end-to-end/auth.js b/test/end-to-end/auth.js index d19c1320..50ad6884 100644 --- a/test/end-to-end/auth.js +++ b/test/end-to-end/auth.js @@ -286,7 +286,7 @@ describe("Password recovery endpoint test", () => { const res = await request() .get("/auth/recover/token/confirm"); - expect(res.status).toBe(HTTPStatus.FORBIDDEN); + expect(res.status).toBe(HTTPStatus.NOT_FOUND); expect(res.body).toHaveProperty("errors"); expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_TOKEN); }); @@ -325,9 +325,9 @@ describe("Password recovery endpoint test", () => { res = await request() .get(`/auth/recover/${generatedToken}/confirm`); - expect(res.status).toBe(HTTPStatus.FORBIDDEN); + expect(res.status).toBe(HTTPStatus.GONE); expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_TOKEN); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.EXPIRED_TOKEN); Date.now = realTime; }); @@ -339,7 +339,7 @@ describe("Password recovery endpoint test", () => { .post("/auth/recover/token/confirm") .send({ password: newPassword }); - expect(res.status).toBe(HTTPStatus.FORBIDDEN); + expect(res.status).toBe(HTTPStatus.NOT_FOUND); expect(res.body).toHaveProperty("errors"); expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_TOKEN); }); @@ -380,9 +380,9 @@ describe("Password recovery endpoint test", () => { .post(`/auth/recover/${generatedToken}/confirm`) .send({ password: newPassword }); - expect(res.status).toBe(HTTPStatus.FORBIDDEN); + expect(res.status).toBe(HTTPStatus.GONE); expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_TOKEN); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.EXPIRED_TOKEN); Date.now = realTime; }); diff --git a/test/end-to-end/auth/recover/:token/confirm.js b/test/end-to-end/auth/recover/:token/confirm.js new file mode 100644 index 00000000..5ebe2950 --- /dev/null +++ b/test/end-to-end/auth/recover/:token/confirm.js @@ -0,0 +1,188 @@ +import { StatusCodes } from "http-status-codes"; +import Account from "../../../../../src/models/Account"; +import ValidatorTester from "../../../../utils/ValidatorTester"; +import ValidationReasons from "../../../../../src/api/middleware/validators/validationReasons"; +import hash from "../../../../../src/lib/passwordHashing"; +import AccountConstants, { RECOVERY_LINK_EXPIRATION } from "../../../../../src/models/constants/Account"; +import * as token from "../../../../../src/lib/token"; +import env from "../../../../../src/config/env"; +import { SECOND_IN_MS } from "../../../../../src/models/constants/TimeConstants"; +import { generateToken } from "../../../../../src/lib/token"; + +const generateTokenSpy = jest.spyOn(token, "generateToken"); +jest.spyOn(token, "verifyAndDecodeToken"); + +describe("GET /auth/recover/:token/confirm", () => { + + const test_account = { + email: "recover_email@gmail.com", + password: "password123", + }; + + beforeEach(async () => { + await Account.deleteMany({ email: test_account.email }); + + await Account.create({ + email: test_account.email, + password: await hash(test_account.password), + isAdmin: true, + }); + + jest.clearAllMocks(); + }); + + test("should fail if invalid token", async () => { + const res = await request() + .get("/auth/recover/token/confirm"); + + expect(res.status).toBe(StatusCodes.NOT_FOUND); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_TOKEN); + }); + + test("should accept if valid token", async () => { + let res = await request() + .post("/auth/recover/request") + .send({ email: test_account.email }); + + expect(token.generateToken).toHaveBeenCalledWith({ email: test_account.email }, env.jwt_secret, RECOVERY_LINK_EXPIRATION); + + const generatedToken = generateTokenSpy.mock.results[0].value; + expect(res.status).toBe(StatusCodes.OK); + + res = await request() + .get(`/auth/recover/${generatedToken}/confirm`); + + expect(res.status).toBe(StatusCodes.OK); + }); + + test("should fail if valid token expired", async () => { + let res = await request() + .post("/auth/recover/request") + .send({ email: test_account.email }); + + expect(token.generateToken).toHaveBeenCalledWith({ email: test_account.email }, env.jwt_secret, RECOVERY_LINK_EXPIRATION); + + const generatedToken = generateTokenSpy.mock.results[0].value; + expect(res.status).toBe(StatusCodes.OK); + + + const realTime = Date.now; + const mockDate = Date.now() + (RECOVERY_LINK_EXPIRATION * SECOND_IN_MS); + Date.now = () => mockDate; + + res = await request() + .get(`/auth/recover/${generatedToken}/confirm`); + + expect(res.status).toBe(StatusCodes.GONE); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.EXPIRED_TOKEN); + + Date.now = realTime; + }); +}); + +describe("POST /auth/recover/:token/confirm", () => { + + const test_account = { + email: "recover_email@gmail.com", + password: "password123", + }; + + const newPassword = "new_password_123"; + + beforeEach(async () => { + await Account.deleteMany({ email: test_account.email }); + + await Account.create({ + email: test_account.email, + password: await hash(test_account.password), + isAdmin: true, + }); + + jest.clearAllMocks(); + }); + + afterAll(async () => { + await Account.deleteMany({}); + }); + + describe("Input Validation", () => { + describe("password", () => { + let generatedToken; + + beforeAll(async () => { + await request() + .post("/auth/recover/request") + .send({ email: test_account.email }).expect(StatusCodes.OK); + + expect(token.generateToken).toHaveBeenCalledWith({ email: test_account.email }, env.jwt_secret, RECOVERY_LINK_EXPIRATION); + + generatedToken = generateTokenSpy.mock.results[0].value; + }); + + const EndpointValidatorTester = + ValidatorTester((params) => request().post(`/auth/recover/${generatedToken}/confirm`).send(params)); + const BodyValidatorTester = EndpointValidatorTester("body"); + const FieldValidatorTester = BodyValidatorTester("password"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustBeString(); + FieldValidatorTester.hasMinLength(AccountConstants.password.min_length); + FieldValidatorTester.hasNumber(); + }); + }); + + test("should fail if invalid token", async () => { + const res = await request() + .post("/auth/recover/token/confirm") + .send({ password: newPassword }); + + expect(res.status).toBe(StatusCodes.NOT_FOUND); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_TOKEN); + }); + + test("should accept if valid token", async () => { + const generatedToken = generateToken({ email: test_account.email }, env.jwt_secret, RECOVERY_LINK_EXPIRATION); + + const res = await request() + .post(`/auth/recover/${generatedToken}/confirm`) + .send({ password: newPassword }); + + expect(res.status).toBe(StatusCodes.OK); + }); + + test("should fail if valid token expired", async () => { + + const generatedToken = generateToken({ email: test_account.email }, env.jwt_secret, RECOVERY_LINK_EXPIRATION); + + const realTime = Date.now; + const mockDate = Date.now() + (RECOVERY_LINK_EXPIRATION * SECOND_IN_MS); + Date.now = () => mockDate; + + const res = await request() + .post(`/auth/recover/${generatedToken}/confirm`) + .send({ password: newPassword }); + + expect(res.status).toBe(StatusCodes.GONE); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.EXPIRED_TOKEN); + + Date.now = realTime; + }); + + test("should succeed to complete the whole password recovery process", async () => { + const generatedToken = generateToken({ email: test_account.email }, env.jwt_secret, RECOVERY_LINK_EXPIRATION); + + await request() + .post(`/auth/recover/${generatedToken}/confirm`) + .send({ password: newPassword }) + .expect(StatusCodes.OK); + + await request() + .post("/auth/login") + .send({ email: test_account.email, password: newPassword }) + .expect(StatusCodes.OK); + + }); +}); diff --git a/test/end-to-end/company/:companyId/state.js b/test/end-to-end/company/:companyId/state.js index 64aaac32..482f671d 100644 --- a/test/end-to-end/company/:companyId/state.js +++ b/test/end-to-end/company/:companyId/state.js @@ -1,7 +1,6 @@ import { StatusCodes } from "http-status-codes"; import CompanyApplication from "../../../../src/models/CompanyApplication"; import Account from "../../../../src/models/Account"; -import * as token from "../../../../src/lib/token.js"; import Company from "../../../../src/models/Company.js"; import AccountService from "../../../../src/services/account.js"; import CompanyApplicationService from "../../../../src/services/application.js"; diff --git a/test/end-to-end/offer.js b/test/end-to-end/offer.js index d79cfe6b..583a862b 100644 --- a/test/end-to-end/offer.js +++ b/test/end-to-end/offer.js @@ -22,6 +22,7 @@ import EmailService from "../../src/lib/emailService"; import { concurrentOffersNotExceeded } from "../../src/api/middleware/validators/validatorUtils"; import { OFFER_DISABLED_NOTIFICATION } from "../../src/email-templates/companyOfferDisabled"; import base64url from "base64url"; +import CompanyApplication from "../../src/models/CompanyApplication.js"; //---------------------------------------------------------------- describe("Offer endpoint tests", () => { @@ -60,6 +61,15 @@ describe("Offer endpoint tests", () => { beforeAll(async () => { await Company.deleteMany({}); + await CompanyApplication.deleteMany({}); + await CompanyApplication.create({ + email: test_user_company.email, + password: test_user_company.password, + companyName: "test verified company", + motivation: "I want people for job :)", + isVerified: true, + submittedAt: Date.now() + }); test_company = await Company.create({ name: "test company", bio: "a bio", @@ -79,6 +89,11 @@ describe("Offer endpoint tests", () => { company: test_company._id }); }); + afterAll(async () => { + await Company.deleteMany({}); + await Account.deleteMany({}); + await CompanyApplication.deleteMany({}); + }); describe("POST /offers", () => { @@ -1062,6 +1077,7 @@ describe("Offer endpoint tests", () => { owner: test_company._id, ownerName: test_company.name, ownerLogo: test_company.logo, + isPending: false }; await Offer.deleteMany({}); diff --git a/test/end-to-end/offers/index.js b/test/end-to-end/offers/index.js new file mode 100644 index 00000000..f0e05c05 --- /dev/null +++ b/test/end-to-end/offers/index.js @@ -0,0 +1,2145 @@ +import Company from "../../../src/models/Company.js"; +import Offer from "../../../src/models/Offer.js"; +import OfferService from "../../../src/services/offer.js"; +import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; +import { ErrorTypes } from "../../../src/api/middleware/errorHandler.js"; +import ValidationReasons from "../../../src/api/middleware/validators/validationReasons.js"; +import base64url from "base64url"; +import { DAY_TO_MS } from "../../utils/TimeConstants.js"; +import withGodToken from "../../utils/GodToken.js"; +import CompanyApplication from "../../../src/models/CompanyApplication.js"; +import Account from "../../../src/models/Account.js"; +import hash from "../../../src/lib/passwordHashing.js"; + +describe("Using already created offer(s)", () => { + const generateTestOffer = (params) => ({ + title: "Test Offer", + publishDate: (new Date(Date.now())).toISOString(), + publishEndDate: (new Date(Date.now() + (DAY_TO_MS))).toISOString(), + description: "For Testing Purposes", + contacts: ["geral@niaefeup.pt", "229417766"], + jobMinDuration: 1, + jobMaxDuration: 6, + jobType: "SUMMER INTERNSHIP", + fields: ["DEVOPS", "BACKEND", "OTHER"], + technologies: ["React", "CSS"], + location: "Testing Street, Test City, 123", + isHidden: false, + isArchived: false, + requirements: ["The candidate must be tested", "Fluent in testJS"], + vacancies: 2, + ...params, + }); + + const test_agent = agent(); + + const test_user_admin = { + email: "admin@email.com", + password: "password123", + }; + + const test_user_company = { + email: "company@email.com", + password: "password123", + }; + + const approved_test_user_company = { + email: "approvedCompany@email.com", + password: "password123", + }; + + let test_company; + + let approved_test_company; + + let test_offer; + + const testPublishDate = "2019-11-22T00:00:00.000Z"; + + const testPublishEndDate = "2019-11-28T00:00:00.000Z"; + + + const RealDateNow = Date.now; + const mockCurrentDate = new Date("2019-11-23"); + + + beforeAll(async () => { + await Company.deleteMany({}); + await CompanyApplication.deleteMany({}); + + await CompanyApplication.create({ + email: test_user_company.email, + password: test_user_company.password, + companyName: "test verified company", + motivation: "I want people for job :)", + isVerified: true, + submittedAt: Date.now() + }); + + await CompanyApplication.create({ + email: approved_test_user_company.email, + password: approved_test_user_company.password, + companyName: "approved test company", + motivation: "I want people for job :)", + isVerified: true, + submittedAt: Date.now() - 1, + approvedAt: Date.now() + }); + + test_company = await Company.create({ + name: "test company", + bio: "a bio", + contacts: ["a contact"], + hasFinishedRegistration: true, + logo: "http://awebsite.com/alogo.jpg", + }); + + approved_test_company = await Company.create({ + name: "approved test company", + bio: "a bio", + contacts: ["a contact"], + hasFinishedRegistration: true, + logo: "http://awebsite.com/alogo.jpg", + }); + + await Account.deleteMany({}); + + await Account.create({ + email: test_user_admin.email, + password: await hash(test_user_admin.password), + isAdmin: true + }); + + await Account.create({ + email: test_user_company.email, + password: await hash(test_user_company.password), + company: test_company._id + }); + + await Account.create({ + email: approved_test_user_company.email, + password: await hash(approved_test_user_company.password), + company: approved_test_company._id + }); + + test_offer = { + ...generateTestOffer({ + "publishDate": testPublishDate, + "publishEndDate": testPublishEndDate + }), + owner: test_company._id, + ownerName: test_company.name, + ownerLogo: test_company.logo, + isPending: false + }; + + await Offer.deleteMany({}); + await Offer.create(test_offer); + }); + + afterAll(async () => { + await Company.deleteMany({}); + await Account.deleteMany({}); + await CompanyApplication.deleteMany({}); + await Offer.deleteMany({}); + }); + + beforeEach(() => { + Date.now = () => mockCurrentDate.getTime(); + }); + + afterEach(() => { + Date.now = RealDateNow; + }); + + describe("queryToken validation", () => { + test("should fail if queryToken does not contain a valid id", async () => { + const queryToken = (new OfferService()).encodeQueryToken("123", 5, "publishDate", mockCurrentDate, false, "test", {}); + + const res = await request() + .get("/offers") + .query({ queryToken }); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); + expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); + expect(res.body.errors[0]).toHaveProperty("location", "query"); + }); + + test("should fail if the queryToken's offer does not exist", async () => { + const queryToken = (new OfferService()) + .encodeQueryToken("5facf0cdb8bc30016ee58952", 5, "publishDate", mockCurrentDate, false, "test", {}); + const res = await request() + .get("/offers") + .query({ queryToken }); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); + expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); + expect(res.body.errors[0]).toHaveProperty("location", "query"); + }); + + test("should fail if the queryToken's score is not a number", async () => { + const testOfferId = (await Offer.findOne({}))._id; + const queryToken = (new OfferService()) + .encodeQueryToken(testOfferId, "hello", "test", "test", false, "test", {}); + + const res = await request() + .get("/offers") + .query({ queryToken }); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); + expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); + expect(res.body.errors[0]).toHaveProperty("location", "query"); + }); + + test("should fail if the queryToken's score is negative", async () => { + const testOfferId = (await Offer.findOne({}))._id; + const queryToken = (new OfferService()) + .encodeQueryToken(testOfferId, -5, "publishDate", mockCurrentDate, false, "test", {}); + + const res = await request() + .get("/offers") + .query({ queryToken }); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); + expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); + expect(res.body.errors[0]).toHaveProperty("location", "query"); + }); + + test("should fail if the queryToken's value is present and score is missing", async () => { + const testOfferId = (await Offer.findOne({}))._id; + const queryToken = (new OfferService()) + .encodeQueryToken(testOfferId, undefined, "test", "test", false, "test", {}); + + const res = await request() + .get("/offers") + .query({ queryToken }); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); + expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); + expect(res.body.errors[0]).toHaveProperty("location", "query"); + }); + + test("should fail if the queryToken's score is present and value is missing", async () => { + const testOfferId = (await Offer.findOne({}))._id; + const queryToken = (new OfferService()) + .encodeQueryToken(testOfferId, 5, "publishDate", mockCurrentDate, false, undefined, {}); + + const res = await request() + .get("/offers") + .query({ queryToken }); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); + expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); + expect(res.body.errors[0]).toHaveProperty("location", "query"); + }); + + test("should fail if the queryToken's publishDate is not a date", async () => { + const testOfferId = (await Offer.findOne({}))._id; + const queryToken = base64url.encode(JSON.stringify({ + id: testOfferId, score: 5, sortField: "publishDate", sortValue: "help", sortDescending: true, value: 5 + })); + + const res = await request() + .get("/offers") + .query({ queryToken }); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); + expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); + expect(res.body.errors[0]).toHaveProperty("location", "query"); + }); + + test("should fail if the queryToken's publishEndDate is not a date", async () => { + const testOfferId = (await Offer.findOne({}))._id; + const queryToken = base64url.encode(JSON.stringify({ + id: testOfferId, score: 5, sortField: "publishEndDate", sortValue: "help", sortDescending: true, value: 5 + })); + + const res = await request() + .get("/offers") + .query({ queryToken }); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); + expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); + expect(res.body.errors[0]).toHaveProperty("location", "query"); + }); + + test("should fail if the queryToken's sortValue is missing", async () => { + const testOfferId = (await Offer.findOne({}))._id; + const queryToken = (new OfferService()) + .encodeQueryToken(testOfferId, 5, "test", undefined, true, undefined, {}); + + const res = await request() + .get("/offers") + .query({ queryToken }); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); + expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); + expect(res.body.errors[0]).toHaveProperty("location", "query"); + }); + + test("should fail if the queryToken's sortField is missing", async () => { + const testOfferId = (await Offer.findOne({}))._id; + const queryToken = (new OfferService()) + .encodeQueryToken(testOfferId, 5, undefined, "test", true, undefined, {}); + + const res = await request() + .get("/offers") + .query({ queryToken }); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); + expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); + expect(res.body.errors[0]).toHaveProperty("location", "query"); + }); + + test("should fail if the queryToken's sortDescending is missing", async () => { + const testOfferId = (await Offer.findOne({}))._id; + const queryToken = (new OfferService()) + .encodeQueryToken(testOfferId, 5, "test", "test", undefined, undefined, {}); + + const res = await request() + .get("/offers") + .query({ queryToken }); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); + expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); + expect(res.body.errors[0]).toHaveProperty("location", "query"); + }); + + test("should succeed when the queryToken's value and score are missing", async () => { + const testOfferId = (await Offer.findOne({}))._id; + const queryToken = (new OfferService()) + .encodeQueryToken(testOfferId, undefined, "publishDate", mockCurrentDate, true, undefined, {}); + + const res = await request() + .get("/offers") + .query({ queryToken }); + + expect(res.status).toBe(HTTPStatus.OK); + }); + + test("should succeed when the queryToken's value is present and score is a valid number", async () => { + const testOfferId = (await Offer.findOne({}))._id; + const queryToken = (new OfferService()) + .encodeQueryToken(testOfferId, 5, "test", "test", false, "test", {}); + + const res = await request() + .get("/offers") + .query({ queryToken }); + + expect(res.status).toBe(HTTPStatus.OK); + }); + + test("should succeed when value is present and queryToken's score can be parsed as a number", async () => { + const testOfferId = (await Offer.findOne({}))._id; + const queryToken = (new OfferService()) + .encodeQueryToken(testOfferId, "3.5", "test", "test", false, "test", {}); + + const res = await request() + .get("/offers") + .query({ queryToken }); + + expect(res.status).toBe(HTTPStatus.OK); + }); + }); + + describe("Only current offers are returned", () => { + + const expired_test_offer = generateTestOffer({ + "publishDate": (new Date(Date.now() - (2 * DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() - (DAY_TO_MS))).toISOString() + }); + + const future_test_offer = generateTestOffer({ + "publishDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() + (2 * DAY_TO_MS))).toISOString() + }); + + beforeAll(async () => { + + [expired_test_offer, future_test_offer] + .forEach((offer) => { + offer.owner = test_company._id; + offer.ownerName = test_company.name; + offer.ownerLogo = test_company.logo; + }); + + await Offer.create([future_test_offer]); + }); + + test("should provide only current offer info (no pending offers)", async () => { + + await Offer.create({ ...test_offer, isPending: true, title: "Pending offer" }); + const res = await request() + .get("/offers"); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anything(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; + delete elem["__v"]; + delete elem["createdAt"]; + delete elem["updatedAt"]; + delete elem["score"]; + delete elem["queryToken"]; + return elem; + }); + + const prepared_test_offer = { + ...test_offer, + isHidden: false, + owner: test_offer.owner.toString(), + }; + + expect(extracted_data).toContainEqual(prepared_test_offer); + }); + + + test("should provide only current offer info (no expired or future offers with no value query)", async () => { + const res = await request() + .get("/offers"); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; + delete elem["__v"]; + delete elem["createdAt"]; + delete elem["updatedAt"]; + delete elem["score"]; + delete elem["queryToken"]; + return elem; + }); + const prepared_test_offer = { + ...test_offer, + isHidden: false, + owner: test_offer.owner.toString(), + + }; + + expect(extracted_data).toContainEqual(prepared_test_offer); + }); + + test("should provide only current offer info (no expired or future offers with some value query)", async () => { + const res = await request() + .get("/offers") + .query({ + value: "test", + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; + delete elem["__v"]; + delete elem["createdAt"]; + delete elem["updatedAt"]; + delete elem["score"]; + delete elem["queryToken"]; + return elem; + }); + const prepared_test_offer = { + ...test_offer, + isHidden: false, + owner: test_offer.owner.toString() + }; + + expect(extracted_data).toContainEqual(prepared_test_offer); + }); + + describe("When a limit is given", () => { + beforeAll(async () => { + // Add 2 more offers + await Offer.deleteMany({}); + await Offer.create([test_offer, future_test_offer, test_offer, test_offer]); + }); + + test("Only `limit` number of offers are returned", async () => { + const res = await request() + .get("/offers") + .query({ + limit: 2, + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; + delete elem["updatedAt"]; delete elem["queryToken"]; + return elem; + }); + + const prepared_test_offer = { + ...test_offer, + isHidden: false, + owner: test_offer.owner.toString() + }; + + expect(extracted_data).toContainEqual(prepared_test_offer); + }); + }); + + describe("When queryToken is given", () => { + + beforeAll(async () => { + // Add another offer + await Offer.deleteMany({}); + await Offer.create([test_offer, { ...test_offer, jobType: "FULL-TIME" }, + expired_test_offer, future_test_offer]); + }); + + test("should fetch offers with the id greater than the one provided", async () => { + const res = await request() + .get("/offers") + .query({ limit: 1 }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + const res2 = await request() + .get("/offers") + .query({ queryToken: res.body.queryToken }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + + const offer = res2.body.results[0]; + expect(offer._id).not.toBe(res.body.results[0]._id); + }); + + test("should succeed if there are no more offers after the last one", async () => { + const res = await request() + .get("/offers"); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + + const res2 = await request() + .get("/offers") + .query({ queryToken: res.body.queryToken }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(0); + }); + + test("offers are returned according to filters", async () => { + const res = await request() + .get("/offers") + .query({ + publishDate: testPublishDate, + publishEndDate: testPublishEndDate, + jobType: "FULL-TIME" + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + expect(res.body.results[0].jobType).toBe("FULL-TIME"); + }); + + test("offers are returned according to filters when using queryToken", async () => { + const res = await request() + .get("/offers") + .query({ + publishDate: testPublishDate, + publishEndDate: testPublishEndDate, + fields: ["DEVOPS"], + limit: 1 + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + expect(res.body.results[0].fields).toContainEqual("DEVOPS"); + + const res2 = await request() + .get("/offers") + .query({ + queryToken: res.body.queryToken + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + expect(res2.body.results[0].fields).toContainEqual("DEVOPS"); + + const res3 = await request() + .get("/offers") + .query({ + publishDate: testPublishDate, + publishEndDate: testPublishEndDate, + jobType: "FULL-TIME" + }); + + expect(res3.status).toBe(HTTPStatus.OK); + expect(res3.body?.results).toHaveLength(1); + expect(res3.body.results[0].jobType).toBe("FULL-TIME"); + + const res4 = await request() + .get("/offers") + .query({ + queryToken: res3.body.queryToken + }); + + expect(res4.status).toBe(HTTPStatus.OK); + expect(res4.body?.results).toHaveLength(0); + }); + + describe("When offers have different publish dates", () => { + beforeAll(async () => { + Date.now = () => mockCurrentDate.getTime(); + + const least_recent_offer = generateTestOffer({ + "publishDate": (new Date(Date.now() - (2 * DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() + }); + + const middle_offer1 = generateTestOffer({ + "publishDate": (new Date(Date.now() - (DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() + }); + + const most_recent_offer = generateTestOffer({ + "publishDate": (new Date(Date.now())).toISOString(), + "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() + }); + + Date.now = RealDateNow; + + [least_recent_offer, middle_offer1, middle_offer1, most_recent_offer] + .forEach((offer) => { + offer.owner = test_company._id; + offer.ownerName = test_company.name; + offer.ownerLogo = test_company.logo; + }); + + await Offer.deleteMany({}); + await Offer.create([least_recent_offer, middle_offer1, middle_offer1, most_recent_offer]); + + await test_agent + .post("/auth/login") + .send({ + email: test_user_company.email, + password: test_user_company.password, + }); + }); + + afterAll(async () => { + await test_agent + .delete("/auth/login"); + await Offer.deleteMany({}); + await Offer.create([test_offer, { ...test_offer, jobType: "FULL-TIME" }, + expired_test_offer, future_test_offer]); + }); + + test("Offers should be sorted by publishDate in descending order and then by id", async () => { + const res = await test_agent + .get("/offers"); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body.results).toHaveLength(4); + + for (let i = 0; i < res.body.results.length - 1; i++) { + try { + expect((new Date(res.body.results[i].publishDate)).getTime()) + .toBeGreaterThan((new Date(res.body.results[i + 1].publishDate)).getTime()); + } catch { + expect(res.body.results[i].publishDate) + .toBe(res.body.results[i + 1].publishDate); + + expect(res.body.results[i]._id < res.body.results[i + 1]._id) + .toBeTruthy(); + } + } + }); + + test("Should return next most recent offer", async () => { + const res1 = await test_agent + .get("/offers") + .query({ + limit: 3 + }); + + expect(res1.status).toBe(HTTPStatus.OK); + expect(res1.body.results).toHaveLength(3); + + const res2 = await test_agent + .get("/offers") + .query({ + queryToken: res1.body.queryToken, + limit: 1 + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body.results).toHaveLength(1); + expect((new Date(res2.body.results[0].publishDate)).getTime()) + .toBeLessThan((new Date(res1.body.results[2].publishDate)).getTime()); + }); + + test("Should return next offer that is as recent but with a higher id", async () => { + const res1 = await test_agent + .get("/offers") + .query({ + limit: 2 + }); + + expect(res1.status).toBe(HTTPStatus.OK); + expect(res1.body.results).toHaveLength(2); + + const res2 = await test_agent + .get("/offers") + .query({ + queryToken: res1.body.queryToken, + limit: 1 + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body.results).toHaveLength(1); + expect(res2.body.results[0]._id > res1.body.results[1]._id) + .toBeTruthy(); + }); + }); + }); + + describe("When showHidden is active", () => { + + beforeAll(async () => { + // Add 1 hidden offer + await Offer.deleteMany({}); + await Offer.create([test_offer, { ...test_offer, isHidden: true }]); + + }); + + test("Should not return hidden offers by default", async () => { + await test_agent + .post("/auth/login") + .send({ + email: test_user_company.email, + password: test_user_company.password, + }); + + const res = await test_agent + .get("/offers"); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; + delete elem["updatedAt"]; delete elem["queryToken"]; + return elem; + }); + + const prepared_test_offer = { + ...test_offer, + isHidden: false, + owner: test_offer.owner.toString() + }; + + expect(extracted_data).toContainEqual(prepared_test_offer); + }); + + test("Only admins can use showHidden", async () => { + await test_agent + .post("/auth/login") + .send({ + email: test_user_company.email, + password: test_user_company.password, + }); + + const res = await test_agent + .get("/offers") + .query({ + showHidden: true, + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; + delete elem["updatedAt"]; delete elem["queryToken"]; + return elem; + }); + + const prepared_test_offer = { + ...test_offer, + isHidden: false, + owner: test_offer.owner.toString() + }; + + expect(extracted_data).toContainEqual(prepared_test_offer); + }); + + test("Only admins can use showHidden (with admin)", async () => { + await test_agent + .post("/auth/login") + .send({ + email: test_user_admin.email, + password: test_user_admin.password, + }); + + const res = await test_agent + .get("/offers") + .query({ + showHidden: true, + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; + delete elem["updatedAt"]; delete elem["queryToken"]; + return elem; + }); + + const prepared_test_offer = { + ...test_offer, + isHidden: false, + owner: test_offer.owner.toString() + }; + + expect(extracted_data).toContainEqual(prepared_test_offer); + }); + }); + + describe("showAdminReason", () => { + + beforeAll(async () => { + await Offer.deleteMany({}); + const test_offers = []; + + for (let i = 0; i < 5; i++) + test_offers.push( + { + ...test_offer, + isHidden: true, + hiddenReason: "ADMIN_REQUEST", + adminReason: "my_reason" + }); + + await Offer.create(test_offers); + }); + + afterEach(async () => { + await test_agent.del("/auth/login"); + }); + + test("should return adminReason if logged as admin", async () => { + + await test_agent + .post("/auth/login") + .send(test_user_admin) + .expect(HTTPStatus.OK); + + const res = await test_agent + .get("/offers") + .query({ + showHidden: true, + }); + + expect(res.status).toBe(HTTPStatus.OK); + + const extracted_data = res.body.results.map((elem) => elem["adminReason"]); + + const expected_data = ["my_reason", "my_reason", "my_reason", "my_reason", "my_reason"]; + + expect(extracted_data).toEqual(expected_data); + }); + + test("should return adminReason if god token is sent", async () => { + + const res = await test_agent + .get("/offers") + .query({ + showHidden: true, + }) + .send(withGodToken()); + + expect(res.status).toBe(HTTPStatus.OK); + + const extracted_data = res.body.results.map((elem) => elem["adminReason"]); + + const expected_data = ["my_reason", "my_reason", "my_reason", "my_reason", "my_reason"]; + + expect(extracted_data).toEqual(expected_data); + }); + + test("should not return adminReason if logged as company", async () => { + + await test_agent + .post("/auth/login") + .send(test_user_company) + .expect(HTTPStatus.OK); + + const res = await test_agent + .get("/offers"); + + expect(res.status).toBe(HTTPStatus.OK); + + const extracted_data = res.body.results.map((elem) => elem["adminReason"]); + + const expected_data = []; + + expect(extracted_data).toEqual(expected_data); + + }); + + test("should not return adminReason if not logged in", async () => { + + const res = await test_agent + .get("/offers"); + + expect(res.status).toBe(HTTPStatus.OK); + + const extracted_data = res.body.results.map((elem) => elem["adminReason"]); + + const expected_data = []; + + expect(extracted_data).toEqual(expected_data); + + }); + }); + }); + + describe("Full text search", () => { + + let portoFrontend; + let portoBackend; + let lisboaBackend; + let niaefeupOffer; + + beforeAll(async () => { + portoFrontend = { + ...test_offer, + title: "This offer is from Porto", + location: "Porto", + jobType: "FULL-TIME", + fields: ["FRONTEND", "OTHER"], + jobMinDuration: 3, + jobMaxDuration: 6 + }; + portoBackend = { + ...test_offer, + location: "Porto", + fields: ["BACKEND", "OTHER"], + jobMinDuration: 2, + jobMaxDuration: 4 + }; + lisboaBackend = { + ...test_offer, + location: "Lisboa", + fields: ["BACKEND", "DEVOPS"] + }; + niaefeupOffer = { + ...test_offer, + location: "FEUP", + fields: ["BLOCKCHAIN", "OTHER"], + ownerName: "NIAEFEUP" + }; + await Offer.deleteMany({}); + await Offer.create([portoBackend, portoFrontend, lisboaBackend, niaefeupOffer]); + }); + + test("should return porto offers", async () => { + + const res = await request() + .get("/offers") + .query({ + value: "porto" + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; + delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; + return elem; + }); + + // eslint-disable-next-line no-unused-vars + const expected_offers = [portoBackend, portoFrontend].map(({ owner, ...offer }) => ({ + ...offer, + isHidden: false, + owner: owner.toString() + })); + + expected_offers.forEach((expected) => { + expect(extracted_data).toContainEqual(expected); + }); + }); + + test("should return niaefeup (company) offers", async () => { + + const res = await request() + .get("/offers") + .query({ + value: "niaefeup" + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; + delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; + return elem; + }); + + const prepared_test_offer = { + ...niaefeupOffer, + isHidden: false, + owner: niaefeupOffer.owner.toString() + }; + + expect(extracted_data).toContainEqual(prepared_test_offer); + }); + + test("should return porto offers in order", async () => { + + const res = await request() + .get("/offers") + .query({ + value: "porto frontend" + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; + delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; + return elem; + }); + + // eslint-disable-next-line no-unused-vars + const expected_offers = [portoFrontend, portoBackend].map(({ owner, ...offer }) => ({ + ...offer, + isHidden: false, + owner: owner.toString() + })); + + expected_offers.forEach((expected, i) => { + expect(extracted_data[i]).toEqual(expected); + }); + }); + + test("should return porto offers for FULL-TIME", async () => { + + const res = await request() + .get("/offers") + .query({ + value: "porto", + jobType: "FULL-TIME" + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; + delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; + return elem; + }); + + const prepared_test_offer = { + ...portoFrontend, + isHidden: false, + owner: portoFrontend.owner.toString() + }; + + expect(extracted_data).toContainEqual(prepared_test_offer); + }); + + test("should return porto offers with React", async () => { + + const res = await request() + .get("/offers") + .query({ + value: "porto", + technologies: ["React"] + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; + delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; + return elem; + }); + + // eslint-disable-next-line no-unused-vars + const expected_offers = [portoFrontend, portoBackend].map(({ owner, ...offer }) => ({ + ...offer, + isHidden: false, + owner: owner.toString() + })); + + expected_offers.forEach((expected) => { + expect(extracted_data).toContainEqual(expected); + }); + }); + + test("should return offers with DEVOPS", async () => { + + const res = await request() + .get("/offers") + .query({ + fields: ["DEVOPS"] + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; + delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; + return elem; + }); + + const prepared_test_offer = { + ...lisboaBackend, + isHidden: false, + owner: lisboaBackend.owner.toString() + }; + + expect(extracted_data).toContainEqual(prepared_test_offer); + }); + + test("should return porto offers with min duration of 2", async () => { + + const res = await request() + .get("/offers") + .query({ + value: "porto", + jobMinDuration: 2 + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; + delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; + return elem; + }); + + // eslint-disable-next-line no-unused-vars + const expected_offers = [portoFrontend, portoBackend].map(({ owner, ...offer }) => ({ + ...offer, + isHidden: false, + owner: owner.toString() + })); + + expected_offers.forEach((expected) => { + expect(extracted_data).toContainEqual(expected); + }); + }); + + test("should return porto offers with min duration of 2 and max duration of 4", async () => { + + // This test should include the 3-6 offer as well, since [3,6] intersects [2,4] + + const res = await request() + .get("/offers") + .query({ + value: "porto", + jobMinDuration: 2, + jobMaxDuration: 4 + }); + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + + // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) + const extracted_data = res.body.results.map((elem) => { + delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; + delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; + return elem; + }); + + // eslint-disable-next-line no-unused-vars + const expected_offers = [portoBackend, portoFrontend].map(({ owner, ...offer }) => ({ + ...offer, + isHidden: false, + owner: owner.toString() + })); + + expected_offers.forEach((expected) => { + expect(extracted_data).toContainEqual(expected); + }); + }); + + describe("When queryToken and value are given", () => { + + test("should return next matching offer with lower score", async () => { + const res = await request() + .get("/offers") + .query({ + value: "porto", + limit: 1 + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + expect(res.body.results[0].title).toEqual(portoFrontend.title); + + const res2 = await request() + .get("/offers") + .query({ + value: "porto", + queryToken: res.body.queryToken + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + expect(res2.body.results[0].title).toEqual(portoBackend.title); + }); + + test("should return next matching offer with the same score", async () => { + const res = await request() + .get("/offers") + .query({ + value: "backend", + limit: 1 + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + const res2 = await request() + .get("/offers") + .query({ + value: "backend", + queryToken: res.body.queryToken + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + }); + + describe("With offers with different publish dates", () => { + beforeAll(async () => { + Date.now = () => mockCurrentDate.getTime(); + + const bestScoreMostRecent = { + ...test_offer, + title: "This offer is from Porto", + "publishDate": (new Date(Date.now() - (DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() + }; + + const bestScoreLeastRecent = { + ...test_offer, + title: "This offer is from Porto", + "publishDate": (new Date(Date.now() - (2 * DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() + }; + + const worstScore = { + ...test_offer, + title: "This offer is from Braga", + location: "Porto", + "publishDate": (new Date(Date.now() - (DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() + }; + + Date.now = RealDateNow; + + await Offer.deleteMany({}); + await Offer.create([bestScoreMostRecent, bestScoreMostRecent, bestScoreLeastRecent, worstScore, worstScore]); + + await test_agent + .post("/auth/login") + .send({ + email: test_user_company.email, + password: test_user_company.password, + }); + }); + + afterAll(async () => { + await Offer.deleteMany({}); + await Offer.create([portoBackend, portoFrontend, lisboaBackend, niaefeupOffer]); + await test_agent + .delete("/auth/login"); + }); + + test("Offers should be ordered by score, publishDate and id in that order", async () => { + const res = await test_agent + .get("/offers") + .query({ + value: "Porto" + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body.results).toHaveLength(5); + + for (let i = 0; i < res.body.results.length - 1; i++) { + try { + expect(Number(res.body.results[i].score)) + .toBeGreaterThan(Number(res.body.results[i + 1].score)); + } catch { + try { + expect(res.body.results[i].score) + .toBe(res.body.results[i + 1].score); + expect((new Date(res.body.results[i].publishDate)).getTime()) + .toBeGreaterThan((new Date(res.body.results[i + 1].publishDate)).getTime()); + } catch { + expect(res.body.results[i].score) + .toBe(res.body.results[i + 1].score); + expect(res.body.results[i].publishDate) + .toBe(res.body.results[i + 1].publishDate); + + expect(res.body.results[i]._id < res.body.results[i + 1]._id) + .toBeTruthy(); + } + } + } + }); + + test("Should return next offer with less score", async () => { + const res1 = await test_agent + .get("/offers") + .query({ + value: "Porto", + limit: 3 + }); + + expect(res1.status).toBe(HTTPStatus.OK); + expect(res1.body.results).toHaveLength(3); + + const res2 = await test_agent + .get("/offers") + .query({ + queryToken: res1.body.queryToken, + limit: 1 + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body.results).toHaveLength(1); + expect(Number(res2.body.results[0].score)) + .toBeLessThan(Number(res1.body.results[2].score)); + }); + + + test("Should return next offer with same score but least recent", async () => { + const res1 = await test_agent + .get("/offers") + .query({ + value: "Porto", + limit: 2 + }); + + expect(res1.status).toBe(HTTPStatus.OK); + expect(res1.body.results).toHaveLength(2); + + const res2 = await test_agent + .get("/offers") + .query({ + queryToken: res1.body.queryToken, + limit: 1 + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body.results).toHaveLength(1); + expect((new Date(res2.body.results[0].publishDate)).getTime()) + .toBeLessThan((new Date(res1.body.results[1].publishDate)).getTime()); + }); + + test("Should return next offer with same score and publishDate but higher id", async () => { + const res1 = await test_agent + .get("/offers") + .query({ + value: "Porto", + limit: 4 + }); + + expect(res1.status).toBe(HTTPStatus.OK); + expect(res1.body.results).toHaveLength(4); + + const res2 = await test_agent + .get("/offers") + .query({ + queryToken: res1.body.queryToken, + limit: 1 + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body.results).toHaveLength(1); + + expect(res2.body.results[0]._id > res1.body.results[3]._id) + .toBeTruthy(); + }); + + test("Should succeed if there are no more offers after the last one", async () => { + const res1 = await test_agent + .get("/offers") + .query({ + value: "Porto" + }); + + expect(res1.status).toBe(HTTPStatus.OK); + expect(res1.body.results).toHaveLength(5); + + const res2 = await test_agent + .get("/offers") + .query({ + queryToken: res1.body.queryToken + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body.results).toHaveLength(0); + }); + }); + + describe("With not current offers", () => { + + const expired_test_offer = generateTestOffer({ + "publishDate": (new Date(Date.now() - (2 * DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() - (DAY_TO_MS))).toISOString() + }); + const future_test_offer = generateTestOffer({ + "publishDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() + (2 * DAY_TO_MS))).toISOString() + }); + + beforeAll(async () => { + + [future_test_offer, expired_test_offer] + .forEach((offer) => { + offer.owner = test_company._id; + offer.ownerName = test_company.name; + offer.ownerLogo = test_company.logo; + }); + + await Offer.create([expired_test_offer, future_test_offer]); + }); + + afterAll(async () => { + await Offer.deleteOne(future_test_offer); + await Offer.deleteOne(expired_test_offer); + }); + + test("should provide only current offers", async () => { + const res = await request() + .get("/offers") + .query({ + value: "porto", + limit: 1 + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + const res2 = await request() + .get("/offers") + .query({ + value: "porto", + queryToken: res.body.queryToken + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + + res2.body.results.forEach((offer) => { + expect(offer.publishDate <= new Date(Date.now()).toISOString()).toBeTruthy(); + expect(offer.publishEndDate >= new Date(Date.now()).toISOString()).toBeTruthy(); + }); + }); + }); + + describe("When queryToken and value are provided and showHidden is active", () => { + + beforeAll(async () => { + await Offer.create({ + ...portoFrontend, + isHidden: true, + title: "This offer is hidden" + }); + }); + + afterAll(async () => { + await Offer.deleteOne({ isHidden: true }); + }); + + test("should not return hidden offers by default", async () => { + const res = await request() + .get("/offers") + .query({ + value: "porto", + limit: 1 + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + const res2 = await request() + .get("/offers") + .query({ + value: "porto", + queryToken: res.body.queryToken + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + + res2.body.results.forEach((offer) => { + expect(offer.isHidden).toBeFalsy(); + }); + }); + + test("companies should not see their hidden offers", async () => { + await test_agent + .post("/auth/login") + .send(test_user_company) + .expect(HTTPStatus.OK); + + const res = await test_agent + .get("/offers") + .query({ + value: "porto", + showHidden: true, + limit: 1 + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + const res2 = await test_agent + .get("/offers") + .query({ + value: "porto", + queryToken: res.body.queryToken + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + + res2.body.results.forEach((offer) => { + expect(offer.isHidden).toBeFalsy(); + }); + }); + + test("admins should see hidden offers", async () => { + await test_agent + .post("/auth/login") + .send(test_user_admin) + .expect(HTTPStatus.OK); + + const res = await test_agent + .get("/offers") + .query({ + value: "porto", + showHidden: true, + limit: 1 + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + const res2 = await test_agent + .get("/offers") + .query({ + value: "porto", + showHidden: true, + queryToken: res.body.queryToken + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(2); + }); + + test("should see hidden offers if god token is sent", async () => { + const res = await test_agent + .get("/offers") + .query({ + value: "porto", + showHidden: true, + limit: 1 + }) + .send(withGodToken()); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + const res2 = await test_agent + .get("/offers") + .query({ + value: "porto", + showHidden: true, + queryToken: res.body.queryToken + }) + .send(withGodToken()); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(2); + }); + }); + + describe("When queryToken and value are provided and adminReason is set", () => { + beforeAll(async () => { + await Offer.create({ + ...portoFrontend, + title: "This offer was hidden by an admin", + isHidden: true, + hiddenReason: "ADMIN_REQUEST", + adminReason: "test_reason" + }); + }); + + afterAll(async () => { + await Offer.deleteOne({ isHidden: true }); + }); + + test("should return adminReason if logged in as admin", async () => { + await test_agent + .post("/auth/login") + .send(test_user_admin) + .expect(HTTPStatus.OK); + + const res = await test_agent + .get("/offers") + .query({ + value: "porto", + showHidden: true, + limit: 1 + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + const res2 = await test_agent + .get("/offers") + .query({ + value: "porto", + showHidden: true, + queryToken: res.body.queryToken + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(2); + + res2.body.results.filter((offer) => offer.isHidden).forEach((offer) => { + expect(offer.hiddenReason).toBe("ADMIN_REQUEST"); + expect(offer.adminReason).toBe("test_reason"); + }); + }); + + test("should return adminReason if god token is sent", async () => { + const res = await test_agent + .get("/offers") + .query({ + value: "porto", + showHidden: true, + limit: 1 + }) + .send(withGodToken()); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + + const res2 = await test_agent + .get("/offers") + .query({ + value: "porto", + showHidden: true, + queryToken: res.body.queryToken + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(2); + + res2.body.results.filter((offer) => offer.isHidden).forEach((offer) => { + expect(offer.hiddenReason).toBe("ADMIN_REQUEST"); + expect(offer.adminReason).toBe("test_reason"); + }); + }); + + test("companies should not see admin reason for their own offers", async () => { + await test_agent + .post("/auth/login") + .send(test_user_company) + .expect(HTTPStatus.OK); + + const res = await test_agent + .get("/offers") + .query({ + value: "porto", + showHidden: true, + limit: 1 + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + expect(res.body.results[0].adminReason).toBeUndefined(); + + const res2 = await test_agent + .get("/offers") + .query({ + value: "porto", + showHidden: true, + queryToken: res.body.queryToken + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + res2.body.results.forEach((offer) => { + expect(offer.adminReason).toBeUndefined(); + }); + }); + + test("should not return admin reason if not logged in", async () => { + const res = await test_agent + .get("/offers") + .query({ + value: "porto", + showHidden: true, + limit: 1 + }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + expect(res.body.results[0].adminReason).toBeUndefined(); + + const res2 = await test_agent + .get("/offers") + .query({ + value: "porto", + showHidden: true, + queryToken: res.body.queryToken + }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + res2.body.results.forEach((offer) => { + expect(offer.adminReason).toBeUndefined(); + }); + }); + }); + }); + }); + + describe("Offer requirements", () => { + + beforeAll(async () => { + await Offer.deleteMany(); + await Offer.create(test_offer); + }); + + test("should return an array of requirements", async () => { + + const res = await request() + .get("/offers"); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + expect(res.body.results[0].requirements).toEqual(test_offer.requirements); + }); + }); + + describe("Offer sorting", () => { + beforeAll(async () => { + await Offer.deleteMany(); + await Offer.create(test_offer); + + await Offer.create({ + ...test_offer, + title: "Amazing offer", + publishDate: "2019-11-23T00:00:00.000Z", + publishEndDate: "2019-11-29T00:00:00.000Z", + description: "Ability to have an incredible job", + jobType: "OTHER", + location: "Aveiro", + vacancies: 1, + ownerName: "Awesome Company", + }); + }); + + afterAll(async () => { + await Offer.deleteMany({}); + }); + + test("should sort by publishDate by default", async () => { + const res = await request() + .get("/offers"); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe("Amazing offer"); + expect(res.body.results[1].title).toBe(test_offer.title); + }); + + test("should sort by title ascending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "title" }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe("Amazing offer"); + expect(res.body.results[1].title).toBe(test_offer.title); + }); + + test("should sort by title descending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "title", descending: true }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe(test_offer.title); + expect(res.body.results[1].title).toBe("Amazing offer"); + }); + + test("should sort by publishDate ascending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "publishDate" }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe(test_offer.title); + expect(res.body.results[1].title).toBe("Amazing offer"); + }); + + test("should sort by publishDate descending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "publishDate", descending: true }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe("Amazing offer"); + expect(res.body.results[1].title).toBe(test_offer.title); + }); + + test("should sort by publishEndDate ascending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "publishEndDate" }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe(test_offer.title); + expect(res.body.results[1].title).toBe("Amazing offer"); + }); + + test("should sort by publishEndDate descending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "publishEndDate", descending: true }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe("Amazing offer"); + expect(res.body.results[1].title).toBe(test_offer.title); + }); + + test("should sort by description ascending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "description" }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe("Amazing offer"); + expect(res.body.results[1].title).toBe(test_offer.title); + }); + + test("should sort by description descending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "description", descending: true }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe(test_offer.title); + expect(res.body.results[1].title).toBe("Amazing offer"); + }); + + test("should sort by jobType ascending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "jobType" }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe("Amazing offer"); + expect(res.body.results[1].title).toBe(test_offer.title); + }); + + test("should sort by jobType descending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "jobType", descending: true }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe(test_offer.title); + expect(res.body.results[1].title).toBe("Amazing offer"); + }); + + test("should sort by location ascending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "location" }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe("Amazing offer"); + expect(res.body.results[1].title).toBe(test_offer.title); + }); + + test("should sort by location descending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "location", descending: true }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe(test_offer.title); + expect(res.body.results[1].title).toBe("Amazing offer"); + }); + + test("should sort by vacancies ascending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "vacancies" }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe("Amazing offer"); + expect(res.body.results[1].title).toBe(test_offer.title); + }); + + test("should sort by vacancies descending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "vacancies", descending: true }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe(test_offer.title); + expect(res.body.results[1].title).toBe("Amazing offer"); + }); + + test("should sort by ownerName ascending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "ownerName" }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe("Amazing offer"); + expect(res.body.results[1].title).toBe(test_offer.title); + }); + + test("should sort by ownerName descending", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "ownerName", descending: true }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(2); + expect(res.body.results[0].title).toBe(test_offer.title); + expect(res.body.results[1].title).toBe("Amazing offer"); + }); + + describe("Using pagination", () => { + beforeAll(async () => { + await Offer.deleteMany(); + await Offer.create(test_offer); + + await Offer.create({ + ...test_offer, + title: "Amazing offer", + publishDate: "2019-11-23T00:00:00.000Z", + publishEndDate: "2019-11-29T00:00:00.000Z", + description: "Ability to have an incredible job", + jobType: "OTHER", + location: "Aveiro", + ownerName: "Awesome Company", + vacancies: 3, + }); + }); + + afterAll(async () => { + await Offer.deleteMany({}); + }); + + test("should sort by title in multiple pages", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "title", limit: 1 }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + expect(res.body.results[0].title).toBe("Amazing offer"); + + const res2 = await request() + .get("/offers") + .query({ limit: 1, queryToken: res.body.queryToken }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + expect(res2.body.results[0].title).toBe(test_offer.title); + }); + + test("should sort by publishEndDate in multiple pages", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "publishEndDate", limit: 1 }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + expect(res.body.results[0].title).toBe(test_offer.title); + + const res2 = await request() + .get("/offers") + .query({ limit: 1, queryToken: res.body.queryToken }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + expect(res2.body.results[0].title).toBe("Amazing offer"); + }); + + test("should sort by description in multiple pages", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "description", limit: 1 }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + expect(res.body.results[0].title).toBe("Amazing offer"); + + const res2 = await request() + .get("/offers") + .query({ limit: 1, queryToken: res.body.queryToken }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + expect(res2.body.results[0].title).toBe(test_offer.title); + }); + + test("should sort by jobType in multiple pages", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "jobType", limit: 1 }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + expect(res.body.results[0].title).toBe("Amazing offer"); + + const res2 = await request() + .get("/offers") + .query({ limit: 1, queryToken: res.body.queryToken }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + expect(res2.body.results[0].title).toBe(test_offer.title); + }); + + test("should sort by location in multiple pages", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "location", limit: 1 }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + expect(res.body.results[0].title).toBe("Amazing offer"); + + const res2 = await request() + .get("/offers") + .query({ limit: 1, queryToken: res.body.queryToken }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + expect(res2.body.results[0].title).toBe(test_offer.title); + }); + + test("should sort by vacancies in multiple pages", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "vacancies", limit: 1 }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + expect(res.body.results[0].title).toBe(test_offer.title); + + const res2 = await request() + .get("/offers") + .query({ limit: 1, queryToken: res.body.queryToken }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + expect(res2.body.results[0].title).toBe("Amazing offer"); + }); + + test("should sort by ownerName in multiple pages", async () => { + const res = await request() + .get("/offers") + .query({ sortBy: "ownerName", limit: 1 }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body?.results).toHaveLength(1); + expect(res.body.results[0].title).toBe("Amazing offer"); + + const res2 = await request() + .get("/offers") + .query({ limit: 1, queryToken: res.body.queryToken }); + + expect(res2.status).toBe(HTTPStatus.OK); + expect(res2.body?.results).toHaveLength(1); + expect(res2.body.results[0].title).toBe(test_offer.title); + }); + }); + }); +}); diff --git a/test/end-to-end/offers/new.js b/test/end-to-end/offers/new.js new file mode 100644 index 00000000..8f7229af --- /dev/null +++ b/test/end-to-end/offers/new.js @@ -0,0 +1,1056 @@ +import { DAY_TO_MS } from "../../utils/TimeConstants.js"; +import Company from "../../../src/models/Company.js"; +import Account from "../../../src/models/Account.js"; +import hash from "../../../src/lib/passwordHashing.js"; +import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; +import ValidationReasons from "../../../src/api/middleware/validators/validationReasons.js"; +import { ErrorTypes } from "../../../src/api/middleware/errorHandler.js"; +import withGodToken from "../../utils/GodToken.js"; +import ValidatorTester from "../../utils/ValidatorTester.js"; +import OfferConstants from "../../../src/models/constants/Offer.js"; +import JobTypes from "../../../src/models/constants/JobTypes.js"; +import * as FieldConstants from "../../../src/models/constants/FieldTypes.js"; +import * as TechnologyConstants from "../../../src/models/constants/TechnologyTypes.js"; +import Offer from "../../../src/models/Offer.js"; +import { MONTH_IN_MS, OFFER_MAX_LIFETIME_MONTHS } from "../../../src/models/constants/TimeConstants.js"; +import CompanyConstants from "../../../src/models/constants/Company.js"; +import CompanyApplication from "../../../src/models/CompanyApplication.js"; + +describe("Offer endpoint tests", () => { + const generateTestOffer = (params) => ({ + title: "Test Offer", + publishDate: (new Date(Date.now())).toISOString(), + publishEndDate: (new Date(Date.now() + (DAY_TO_MS))).toISOString(), + description: "For Testing Purposes", + contacts: ["geral@niaefeup.pt", "229417766"], + jobMinDuration: 1, + jobMaxDuration: 6, + jobType: "SUMMER INTERNSHIP", + fields: ["DEVOPS", "BACKEND", "OTHER"], + technologies: ["React", "CSS"], + location: "Testing Street, Test City, 123", + isHidden: false, + isArchived: false, + requirements: ["The candidate must be tested", "Fluent in testJS"], + vacancies: 2, + ...params, + }); + + let test_company, approved_test_company; + + const test_agent = agent(); + + const test_user_admin = { + email: "admin@email.com", + password: "password123", + }; + const test_user_company = { + email: "company@email.com", + password: "password123", + }; + + const approved_test_user_company = { + email: "approvedCompany@email.com", + password: "password123", + }; + + beforeAll(async () => { + + await Company.deleteMany({}); + + await Account.deleteMany({}); + + await CompanyApplication.deleteMany({}); + + test_company = await Company.create({ + name: "test company", + bio: "a bio", + contacts: ["a contact"], + hasFinishedRegistration: true, + logo: "http://awebsite.com/alogo.jpg", + }); + + approved_test_company = await Company.create({ + name: " approved test company", + bio: "a bio", + contacts: ["a contact"], + hasFinishedRegistration: true, + logo: "http://awebsite.com/alogo.jpg", + }); + + await CompanyApplication.create({ + email: test_user_company.email, + password: test_user_company.password, + companyName: "test verified company", + motivation: "I want people for job :)", + isVerified: true, + submittedAt: Date.now() + }); + + await CompanyApplication.create({ + email: approved_test_user_company.email, + password: approved_test_user_company.password, + companyName: "approved test company", + motivation: "I want people for job :)", + isVerified: true, + submittedAt: Date.now() - 1, + approvedAt: Date.now(), + }); + + await Account.create({ + email: test_user_admin.email, + password: await hash(test_user_admin.password), + isAdmin: true + }); + + await Account.create({ + email: test_user_company.email, + password: await hash(test_user_company.password), + company: test_company._id, + }); + + await Account.create({ + email: approved_test_user_company.email, + password: await hash(approved_test_user_company.password), + company: approved_test_company._id, + }); + + }); + + afterAll(async () => { + await Company.deleteMany({}); + await Account.deleteMany({}); + await CompanyApplication.deleteMany({}); + }); + + describe("POST /offers", () => { + + describe("Authentication", () => { + + describe("creating offers requires company account or admin account (without god token)", () => { + test("should fail if not logged in", async () => { + const res = await request() + .post("/offers/new") + .send({}); + + expect(res.status).toBe(HTTPStatus.UNAUTHORIZED); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors).toContainEqual({ msg: ValidationReasons.INSUFFICIENT_PERMISSIONS }); + }); + + test("should fail if not logged in, even if target owner is specified", async () => { + const params = { owner: test_company._id }; + const offer = generateTestOffer(params); + + const res = await request() + .post("/offers/new") + .send(offer); + + expect(res.status).toBe(HTTPStatus.UNAUTHORIZED); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors).toContainEqual({ msg: ValidationReasons.INSUFFICIENT_PERMISSIONS }); + }); + + test("should succeed if logged to admin account", async () => { + // Login + await test_agent + .post("/auth/login") + .send(test_user_admin) + .expect(200); + + const params = { owner: test_company._id }; + const offer = generateTestOffer(params); + const res = await test_agent + .post("/offers/new") + .send(offer); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body).toHaveProperty("title", offer.title); + expect(res.body).toHaveProperty("description", offer.description); + expect(res.body).toHaveProperty("location", offer.location); + }); + + test("should create offer if logged in to company account", async () => { + + // Login + const offer = { ...generateTestOffer() }; + await test_agent + .post("/auth/login") + .send(test_user_company) + .expect(200); + + const res = await test_agent + .post("/offers/new") + .send({ ...offer }); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body).toHaveProperty("title", offer.title); + expect(res.body).toHaveProperty("description", offer.description); + expect(res.body).toHaveProperty("location", offer.location); + expect(res.body).toHaveProperty("owner", test_company._id.toString()); + expect(res.body).toHaveProperty("ownerName", test_company.name); + expect(res.body).toHaveProperty("ownerLogo", test_company.logo); + }); + }); + + describe("creating offers requires god permissions", () => { + test("should fail when god token not provided", async () => { + const res = await request() + .post("/offers/new") + .send({}); + + expect(res.status).toBe(HTTPStatus.UNAUTHORIZED); + expect(res.body).toHaveProperty("error_code", ErrorTypes.FORBIDDEN); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors).toContainEqual({ msg: ValidationReasons.INSUFFICIENT_PERMISSIONS }); + }); + + test("should fail when god token is incorrect", async () => { + const res = await request() + .post("/offers/new") + .send({ + god_token: "NotAValidGodToken!!12345", + }); + + expect(res.status).toBe(HTTPStatus.UNAUTHORIZED); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors).toContainEqual({ msg: ValidationReasons.INSUFFICIENT_PERMISSIONS }); + }); + + test("should fail when god token is correct but owner doesn't exist", async () => { + const params = { ...generateTestOffer(), owner: "invalidowner" }; + const res = await request() + .post("/offers/new") + .send(withGodToken(params)); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body.errors).toContainEqual({ + value: "invalidowner", + location: "body", + msg: ValidationReasons.COMPANY_NOT_FOUND("invalidowner"), + param: "owner", + }); + + }); + + test("should succeed when god token is correct and owner exists", async () => { + const offer = generateTestOffer(); + const params = { ...offer, owner: test_company._id }; + const res = await request() + .post("/offers/new") + .send(withGodToken(params)); + + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body).toHaveProperty("title", offer.title); + expect(res.body).toHaveProperty("description", offer.description); + expect(res.body).toHaveProperty("location", offer.location); + }); + }); + }); + + const EndpointValidatorTester = ValidatorTester((params) => request().post("/offers/new").send(withGodToken(params))); + const BodyValidatorTester = EndpointValidatorTester("body"); + + describe("Input Validation", () => { + describe("title", () => { + const FieldValidatorTester = BodyValidatorTester("title"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustBeString(); + FieldValidatorTester.hasMinLength(OfferConstants.title.min_length); + FieldValidatorTester.hasMaxLength(OfferConstants.title.max_length); + }); + + describe("publishDate", () => { + const FieldValidatorTester = BodyValidatorTester("publishDate"); + FieldValidatorTester.mustBeDate(); + FieldValidatorTester.mustBeFuture(); + }); + + describe("publishEndDate", () => { + const FieldValidatorTester = BodyValidatorTester("publishEndDate"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustBeDate(); + FieldValidatorTester.mustBeFuture(); + FieldValidatorTester.mustBeAfter("publishDate"); + }); + + describe("jobMinDuration", () => { + const FieldValidatorTester = BodyValidatorTester("jobMinDuration"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustBeNumber(); + }); + + describe("jobMaxDuration", () => { + const FieldValidatorTester = BodyValidatorTester("jobMaxDuration"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustBeNumber(); + FieldValidatorTester.mustBeGreaterThanOrEqualToField("jobMinDuration"); + }); + + describe("jobStartDate", () => { + const FieldValidatorTester = BodyValidatorTester("jobStartDate"); + FieldValidatorTester.mustBeDate(); + }); + + describe("description", () => { + const FieldValidatorTester = BodyValidatorTester("description"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustBeString(); + FieldValidatorTester.hasMaxLength(OfferConstants.description.max_length); + }); + + describe("contacts", () => { + const FieldValidatorTester = BodyValidatorTester("contacts"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustHaveAtLeast(1); + }); + + describe("isPaid", () => { + const FieldValidatorTester = BodyValidatorTester("isPaid"); + FieldValidatorTester.mustBeBoolean(); + }); + + describe("vacancies", () => { + const FieldValidatorTester = BodyValidatorTester("vacancies"); + FieldValidatorTester.mustBeGreaterThanOrEqualTo(OfferConstants.vacancies.min); + }); + + describe("jobType", () => { + const FieldValidatorTester = BodyValidatorTester("jobType"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustBeString(); + FieldValidatorTester.mustBeInArray(JobTypes); + }); + + describe("fields", () => { + const FieldValidatorTester = BodyValidatorTester("fields"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustBeArrayBetween(FieldConstants.MIN_FIELDS, FieldConstants.MAX_FIELDS); + FieldValidatorTester.mustHaveValuesInRange(FieldConstants.FieldTypes, FieldConstants.MIN_FIELDS + 1); + }); + + describe("technologies", () => { + const FieldValidatorTester = BodyValidatorTester("technologies"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustBeArrayBetween(TechnologyConstants.MIN_TECHNOLOGIES, TechnologyConstants.MAX_TECHNOLOGIES); + FieldValidatorTester.mustHaveValuesInRange(TechnologyConstants.TechnologyTypes, TechnologyConstants.MIN_TECHNOLOGIES + 1); + }); + + describe("owner", () => { + const FieldValidatorTester = BodyValidatorTester("owner"); + FieldValidatorTester.isRequired(); + }); + + describe("location", () => { + const FieldValidatorTester = BodyValidatorTester("location"); + FieldValidatorTester.isRequired(); + FieldValidatorTester.mustBeString(); + }); + + describe("requirements", () => { + const FieldValidatorTester = BodyValidatorTester("requirements"); + FieldValidatorTester.isRequired(); + }); + + describe("isHidden", () => { + const FieldValidatorTester = BodyValidatorTester("isHidden"); + FieldValidatorTester.mustBeBoolean(); + }); + }); + + describe("Without pre-existing offers", () => { + beforeAll(async () => { + await Offer.deleteMany({}); + }); + + beforeEach(async () => { + await Offer.deleteMany({}); + }); + + test("Should fail to create an offer due to publish end date being after publish date more than the limit", async () => { + const offer = generateTestOffer(); + const publishDate = new Date(Date.now()); + const offer_params = { + ...offer, + owner: test_company._id, + ownerName: test_company.name, + ownerLogo: test_company.logo, + publishDate: publishDate.toISOString(), + publishEndDate: (new Date(publishDate.getTime() + (MONTH_IN_MS * OFFER_MAX_LIFETIME_MONTHS) + DAY_TO_MS)).toISOString(), + }; + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)); + + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body.errors).toHaveLength(1); + expect(res.body.errors[0]).toHaveProperty("param", "publishEndDate"); + expect(res.body.errors[0]).toHaveProperty("location", "body"); + expect(res.body.errors[0].msg).toEqual( + ValidationReasons.MUST_BE_BEFORE( + new Date(publishDate.getTime() + (MONTH_IN_MS * OFFER_MAX_LIFETIME_MONTHS)).toISOString() + )); + }); + + // TODO: This test should be 'with minimum requirements' + // Thus, there should be another with all of the optional fields being sent, at least + test("Should successfully create an Offer", async () => { + const offer = generateTestOffer(); + const offer_params = { + ...offer, + owner: test_company._id, + }; + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)); + + expect(res.status).toBe(HTTPStatus.OK); + const created_offer_id = res.body._id; + + const created_offer = await Offer.findById(created_offer_id); + + expect(created_offer).toBeDefined(); + // Ideally matchers alongside .toMatchObject should be used in order to check created_offer against offer + // However, no matter what I tried, I couldn't get it to work :upside_down_face: + expect(created_offer).toHaveProperty("title", offer.title); + expect(created_offer).toHaveProperty("description", offer.description); + expect(created_offer).toHaveProperty("location", offer.location); + expect(created_offer).toHaveProperty("ownerName", test_company.name); + expect(created_offer).toHaveProperty("ownerLogo", test_company.logo); + }); + + test("Offer should be pending if the company hasn't been approved", async () => { + const offer = generateTestOffer({ owner: test_company._id }); + const res = await request() + .post("/offers/new") + .send(withGodToken(offer)).expect(HTTPStatus.OK); + expect(res.body.isPending).toBe(true); + }); + + test("Offer should not be pending if the company has been approved", async () => { + const offer = generateTestOffer({ owner: approved_test_company._id }); + const res = await request() + .post("/offers/new") + .send(withGodToken(offer)).expect(HTTPStatus.OK); + expect(res.body.isPending).toBe(false); + }); + + test("Should succeed to create an offer if the description's length is only shorter than the max \ + without HTML tags", async () => { + + const offer_params = { + ...generateTestOffer(), + description: `

${"a".repeat(OfferConstants.description.max_length)}

`, + owner: test_company._id, + }; + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)); + + expect(res.status).toBe(HTTPStatus.OK); + + const created_offer_id = res.body._id; + const created_offer = await Offer.findById(created_offer_id); + + expect(created_offer).toBeDefined(); + expect(created_offer).toHaveProperty("description", offer_params.description); + }); + + test("Should fail to create an offer if the description's length is longer than the max\ + without HTML tags", async () => { + + const offer_params = { + ...generateTestOffer(), + description: `

${"a".repeat(OfferConstants.description.max_length + 1)}

`, + owner: test_company._id, + }; + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body.errors).toHaveLength(1); + expect(res.body.errors[0]).toHaveProperty("param", "description"); + expect(res.body.errors[0]).toHaveProperty("location", "body"); + expect(res.body.errors[0].msg).toEqual(ValidationReasons.TOO_LONG(OfferConstants.description.max_length)); + }); + + test("Should fail to create an offer if jobStartDate is specified as null", async () => { + const offer_params = generateTestOffer({ + jobStartDate: null, + owner: test_company._id + }); + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body.errors).toHaveLength(1); + expect(res.body.errors[0]).toHaveProperty("param", "jobStartDate"); + expect(res.body.errors[0]).toHaveProperty("location", "body"); + expect(res.body.errors[0].msg).toEqual(ValidationReasons.DATE); + }); + + + }); + + describe("Before reaching the offers limit while having past offers", () => { + const testOffers = Array(CompanyConstants.offers.max_concurrent - 1) + .fill(generateTestOffer({ + "publishDate": (new Date(Date.now())).toISOString(), + "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() + })); + + testOffers.push(generateTestOffer({ + "publishDate": (new Date(Date.now() - (3 * DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() - (2 * DAY_TO_MS))).toISOString() + })); + + beforeAll(async () => { + await Offer.deleteMany({}); + + testOffers.forEach((offer) => { + offer.owner = test_company._id; + offer.ownerName = test_company.name; + offer.ownerLogo = test_company.logo; + }); + + await Offer.create(testOffers); + }); + + afterAll(async () => { + await Offer.deleteMany({}); + }); + + test("should be able to create a new offer (past offers do not restrain the company)", async () => { + const offer_params = { + ...generateTestOffer(), + owner: test_company._id, + }; + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body).toHaveProperty("title", offer_params.title); + expect(res.body).toHaveProperty("description", offer_params.description); + expect(res.body).toHaveProperty("location", offer_params.location); + expect(res.body).toHaveProperty("ownerName", test_company.name); + expect(res.body).toHaveProperty("ownerLogo", test_company.logo); + }); + }); + + describe("After reaching the offers limit", () => { + const testOffers = Array(CompanyConstants.offers.max_concurrent) + .fill(generateTestOffer({ + "publishDate": (new Date(Date.now())).toISOString(), + "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() + })); + + beforeAll(async () => { + await Offer.deleteMany({}); + + testOffers.forEach((offer) => { + offer.owner = test_company._id; + offer.ownerName = test_company.name; + offer.ownerLogo = test_company.logo; + }); + + await Offer.create(testOffers); + }); + + afterAll(async () => { + await Offer.deleteMany({}); + }); + + + test("should fail to create a new offer", async () => { + const offer_params = { + ...generateTestOffer(), + owner: test_company._id, + }; + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)); + + expect(res.status).toBe(HTTPStatus.CONFLICT); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors).toContainEqual( + { msg: ValidationReasons.MAX_CONCURRENT_OFFERS_EXCEEDED(CompanyConstants.offers.max_concurrent) }); + }); + + test("should fail to create a new offer (with default publishDate)", async () => { + const offer_params = { + ...generateTestOffer(), + owner: test_company._id, + }; + delete offer_params.publishDate; + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)); + + expect(res.status).toBe(HTTPStatus.CONFLICT); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors).toContainEqual( + { msg: ValidationReasons.MAX_CONCURRENT_OFFERS_EXCEEDED(CompanyConstants.offers.max_concurrent) }); + }); + }); + + describe("Trying to schedule an offer in a time period which reached the offers limit", () => { + const testOffers = Array(CompanyConstants.offers.max_concurrent) + .fill(generateTestOffer({ + "publishDate": (new Date(Date.now() + (3 * DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() + (6 * DAY_TO_MS))).toISOString() + })); + + beforeAll(async () => { + await Offer.deleteMany({}); + + testOffers.forEach((offer) => { + offer.owner = test_company._id; + offer.ownerName = test_company.name; + offer.ownerLogo = test_company.logo; + }); + + await Offer.create(testOffers); + }); + + afterAll(async () => { + await Offer.deleteMany({}); + }); + + test("should fail to schedule a new offer", async () => { + const offer_params = { + ...generateTestOffer({ + "publishDate": (new Date(Date.now() + (4 * DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() + (5 * DAY_TO_MS))).toISOString() + }), + owner: test_company._id, + }; + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)); + + expect(res.status).toBe(HTTPStatus.CONFLICT); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors).toContainEqual( + { msg: ValidationReasons.MAX_CONCURRENT_OFFERS_EXCEEDED(CompanyConstants.offers.max_concurrent) }); + }); + }); + + describe("Creating an offer in a time period with more than `max_concurrent` overlapping offers, \ + without exceeding the limit at any point", () => { + const testOffers = Array(CompanyConstants.offers.max_concurrent - 2) + .fill(generateTestOffer({ + "publishDate": (new Date(Date.now() + (2 * DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() + (10 * DAY_TO_MS))).toISOString() + })); + + testOffers.push(generateTestOffer({ + "publishDate": (new Date(Date.now())).toISOString(), + "publishEndDate": (new Date(Date.now() + (5 * DAY_TO_MS))).toISOString() + })); + + testOffers.push(generateTestOffer({ + "publishDate": (new Date(Date.now() + (8 * DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() + (12 * DAY_TO_MS))).toISOString() + })); + + beforeAll(async () => { + await Offer.deleteMany({}); + + testOffers.forEach((offer) => { + offer.owner = test_company._id; + offer.ownerName = test_company.name; + offer.ownerLogo = test_company.logo; + }); + + await Offer.create(testOffers); + }); + + test("should succeed to create an offer (the offers limit is never reached at any moment)", async () => { + const offer_params = generateTestOffer({ + "publishDate": (new Date(Date.now() + (4 * DAY_TO_MS))).toISOString(), + "publishEndDate": (new Date(Date.now() + (9 * DAY_TO_MS))).toISOString(), + owner: test_company._id, + }); + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)); + + expect(res.status).toBe(HTTPStatus.OK); + expect(res.body.publishDate).toBe(offer_params.publishDate); + expect(res.body.publishEndDate).toBe(offer_params.publishEndDate); + }); + }); + + describe("Default values", () => { + test("publishDate defaults to the current time if not provided", async () => { + const offer = { + title: "Test Offer", + publishEndDate: (new Date(Date.now() + (DAY_TO_MS))).toISOString(), + description: "For Testing Purposes", + contacts: ["geral@niaefeup.pt", "229417766"], + jobType: "SUMMER INTERNSHIP", + jobMinDuration: 1, + jobMaxDuration: 6, + fields: ["DEVOPS", "BACKEND", "OTHER"], + technologies: ["React", "CSS"], + owner: test_company._id, + ownerName: test_company.name, + ownerLogo: test_company.logo, + location: "Testing Street, Test City, 123", + requirements: ["The candidate must be tested", "Fluent in testJS"], + }; + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer)); + + expect(res.status).toBe(HTTPStatus.OK); + const created_offer_id = res.body._id; + + const created_offer = await Offer.findById(created_offer_id); + + expect(created_offer).toBeDefined(); + expect(created_offer).toHaveProperty("title", offer.title); + expect(created_offer).toHaveProperty("description", offer.description); + expect(created_offer).toHaveProperty("location", offer.location); + expect(created_offer).toHaveProperty("publishDate"); + expect(created_offer).toHaveProperty("ownerName", test_company.name); + expect(created_offer).toHaveProperty("ownerLogo", test_company.logo); + }); + }); + + describe("Job Duration", () => { + test("should fail if jobMinDuration is greater than jobMaxDuration", async () => { + const offer_params = generateTestOffer({ + jobMinDuration: 10, + jobMaxDuration: 8, + owner: test_company._id, + }); + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("param", "jobMaxDuration"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.MUST_BE_GREATER_THAN_OR_EQUAL_TO("jobMinDuration")); + }); + + test("should succeed if jobMaxDuration is greater than jobMinDuration", async () => { + const offer_params = generateTestOffer({ + jobMinDuration: 8, + jobMaxDuration: 10, + owner: test_company._id, + }); + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)); + + expect(res.status).toBe(HTTPStatus.OK); + }); + }); + + describe("Same 'publishDate' and 'publishEndDate'", () => { + + const date = (new Date(Date.now() + (DAY_TO_MS))).toISOString(); + let offer; + + beforeAll(() => { + // await Offer.deleteMany({}); + + offer = generateTestOffer({ + publishDate: date, + publishEndDate: date, + owner: test_company._id, + ownerName: test_company.name, + ownerLogo: test_company.logo, + }); + }); + + afterAll(async () => { + await Offer.deleteOne(offer); + }); + + test("should fail if 'publishDate' and 'publishEndDate' have the same value", async () => { + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer)); + + expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); + expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.MUST_BE_AFTER("publishDate")); + expect(res.body.errors[0]).toHaveProperty("param", "publishEndDate"); + expect(res.body.errors[0]).toHaveProperty("location", "body"); + }); + }); + + describe("Incomplete registration of the offer's company", () => { + let incomplete_test_company; + beforeAll(async () => { + incomplete_test_company = await Company.create({ + name: "incomplete test company", + bio: "a bio", + contacts: ["a contact"], + hasFinishedRegistration: false, + logo: "http://awebsite.com/alogo.jpg", + }); + }); + + afterAll(async () => { + await Company.deleteOne({ _id: incomplete_test_company._id }); + }); + + test("should fail to create offer if the company is not fully registered", async () => { + const offer_params = { + ...generateTestOffer(), + owner: incomplete_test_company._id, + ownerName: incomplete_test_company.name, + ownerLogo: incomplete_test_company.logo, + }; + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)); + + expect(res.status).toBe(HTTPStatus.FORBIDDEN); + expect(res.body).toHaveProperty("error_code", ErrorTypes.FORBIDDEN); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors).toContainEqual( + { msg: ValidationReasons.REGISTRATION_NOT_FINISHED }); + }); + }); + + describe("Blocked company", () => { + + let blocked_test_company; + beforeAll(async () => { + blocked_test_company = await Company.create({ + name: "blocked test company", + bio: "a bio", + contacts: ["a contact"], + isBlocked: true, + hasFinishedRegistration: true + }); + }); + + test("should fail to create offer if company blocked", async () => { + const res = await request() + .post("/offers/new") + .send(withGodToken(generateTestOffer({ + owner: blocked_test_company._id, + ownerName: blocked_test_company.name, + }))); + + expect(res.status).toBe(HTTPStatus.FORBIDDEN); + expect(res.body).toHaveProperty("error_code", ErrorTypes.FORBIDDEN); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.COMPANY_BLOCKED); + }); + + }); + + describe("Disabled company", () => { + + let disabled_company; + + const disabled_company_user = { + email: "disabled_company@email.com", + password: "password123", + }; + + beforeAll(async () => { + // await Company.deleteMany({}); + // await Offer.deleteMany({}); + + disabled_company = await Company.create({ + name: "test company", + bio: "a bio", + contacts: ["a contact"], + hasFinishedRegistration: true, + logo: "http://awebsite.com/alogo.jpg", + isDisabled: true, + }); + + await Account.create({ + email: disabled_company_user.email, + password: await hash(disabled_company_user.password), + company: disabled_company._id + }); + }); + + test("Should not create offer if company is disabled, logged in as same company", async () => { + await test_agent + .post("/auth/login") + .send(disabled_company_user) + .expect(HTTPStatus.OK); + + const res = await test_agent + .post("/offers/new") + .send(generateTestOffer()); + + expect(res.status).toBe(HTTPStatus.FORBIDDEN); + expect(res.body).toHaveProperty("error_code", ErrorTypes.FORBIDDEN); + expect(res.body).toHaveProperty("errors"); + expect(res.body.errors).toContainEqual({ msg: ValidationReasons.COMPANY_DISABLED }); + }); + }); + + describe("applyURL validation", () => { + beforeAll(async () => { + await Offer.deleteMany({}); + }); + + beforeEach(async () => { + await Offer.deleteMany({}); + }); + + test("should fail if applyURL is neither a URL or an email", async () => { + const offer_params = generateTestOffer({ + applyURL: "this_is_not_valid", + owner: test_company._id, + }); + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)) + .expect(HTTPStatus.UNPROCESSABLE_ENTITY); + + expect(res.body.errors[0]).toHaveProperty("param", "applyURL"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.BAD_APPLY_URL); + }); + + test("should fail if applyURL is a URL with an unsupported protocol", async () => { + const offer_params = generateTestOffer({ + applyURL: "ftp://www.coolwebsite.com", + owner: test_company._id, + }); + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)) + .expect(HTTPStatus.UNPROCESSABLE_ENTITY); + + expect(res.body.errors[0]).toHaveProperty("param", "applyURL"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.BAD_APPLY_URL); + }); + + test("should fail if applyURL contains javascript code", async () => { + const offer_params = generateTestOffer({ + applyURL: "javascript:alert('hello friend');", + owner: test_company._id, + }); + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)) + .expect(HTTPStatus.UNPROCESSABLE_ENTITY); + + expect(res.body.errors[0]).toHaveProperty("param", "applyURL"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.BAD_APPLY_URL); + }); + + test("should fail if applyURL contains javascript code with a commented valid URL", async () => { + const offer_params = generateTestOffer({ + applyURL: "javascript:alert('hello friend'); // https://www.google.com", + owner: test_company._id, + }); + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)) + .expect(HTTPStatus.UNPROCESSABLE_ENTITY); + + expect(res.body.errors[0]).toHaveProperty("param", "applyURL"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.BAD_APPLY_URL); + }); + + test("should succeed if applyURL is a valid email", async () => { + const applyURL = "mailto:nicemail@gmail.com"; + const offer_params = generateTestOffer({ + applyURL, + owner: test_company._id, + }); + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)) + .expect(HTTPStatus.OK); + + expect(res.body).toHaveProperty("applyURL", applyURL); + }); + + test("should succeed if applyURL is a valid HTTP URL", async () => { + const applyURL = "http://www.coolwebsite.com/a/"; + const offer_params = generateTestOffer({ + applyURL, + owner: test_company._id, + }); + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)) + .expect(HTTPStatus.OK); + + expect(res.body).toHaveProperty("applyURL", applyURL); + }); + + test("should succeed if applyURL is a valid HTTPS URL", async () => { + const applyURL = "https://www.coolwebsite.com"; + const offer_params = generateTestOffer({ + applyURL, + owner: test_company._id, + }); + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)) + .expect(HTTPStatus.OK); + + expect(res.body).toHaveProperty("applyURL", applyURL); + }); + + test("should fail if applyURL is an invalid HTTPS URL", async () => { + const applyURL = "https://invalid"; + const offer_params = generateTestOffer({ + applyURL, + owner: test_company._id, + }); + + const res = await request() + .post("/offers/new") + .send(withGodToken(offer_params)) + .expect(HTTPStatus.UNPROCESSABLE_ENTITY); + + expect(res.body.errors[0]).toHaveProperty("param", "applyURL"); + expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.BAD_APPLY_URL); + }); + }); + + }); +}); From 5d95f3be7d16fbdd8b771f2c41dc386a6b774c23 Mon Sep 17 00:00:00 2001 From: FranciscoCardoso913 Date: Thu, 3 Aug 2023 15:14:45 +0100 Subject: [PATCH 22/30] Fixed tests from token.js and from the review endpoints --- src/api/routes/review.js | 2 +- src/services/application.js | 5 +- test/end-to-end/offer.js | 3 +- test/end-to-end/offers/index.js | 1943 ------------------------------- test/end-to-end/offers/new.js | 952 +-------------- test/end-to-end/review.js | 33 +- test/unit/token.js | 9 +- 7 files changed, 45 insertions(+), 2902 deletions(-) diff --git a/src/api/routes/review.js b/src/api/routes/review.js index dc1719d4..2baa0b1e 100644 --- a/src/api/routes/review.js +++ b/src/api/routes/review.js @@ -87,7 +87,7 @@ export default (app) => { const account = await (new ApplicationService()).approve(req.params.id); const company = await Company.findOne({ _id: account.company }); await (new CompanyService()).releaseOffers(company._id); - return res.json({ account }); + return res.json(account); } catch (err) { console.error(err); if (err instanceof CompanyApplicationNotFound) { diff --git a/src/services/application.js b/src/services/application.js index f80946db..28653fa2 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -183,9 +183,8 @@ class CompanyApplicationService { to: application.email, ...APPROVAL_NOTIFICATION(application.companyName), }); - } catch (e) { - console.error("Error while approving company ", e); - application.undoApproval(); + } catch (err) { + console.error("Error while approving company ", err); throw new CompanyApplicationAlreadyReviewed(CompanyApplicationRules.CANNOT_REVIEW_TWICE.msg); } return Account.findOne({ email: application.email }); diff --git a/test/end-to-end/offer.js b/test/end-to-end/offer.js index 583a862b..daf54bbe 100644 --- a/test/end-to-end/offer.js +++ b/test/end-to-end/offer.js @@ -62,6 +62,7 @@ describe("Offer endpoint tests", () => { beforeAll(async () => { await Company.deleteMany({}); await CompanyApplication.deleteMany({}); + await Account.deleteMany({}); await CompanyApplication.create({ email: test_user_company.email, password: test_user_company.password, @@ -77,7 +78,7 @@ describe("Offer endpoint tests", () => { hasFinishedRegistration: true, logo: "http://awebsite.com/alogo.jpg", }); - await Account.deleteMany({}); + await Account.create({ email: test_user_admin.email, password: await hash(test_user_admin.password), diff --git a/test/end-to-end/offers/index.js b/test/end-to-end/offers/index.js index f0e05c05..efdad084 100644 --- a/test/end-to-end/offers/index.js +++ b/test/end-to-end/offers/index.js @@ -1,12 +1,7 @@ import Company from "../../../src/models/Company.js"; import Offer from "../../../src/models/Offer.js"; -import OfferService from "../../../src/services/offer.js"; import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; -import { ErrorTypes } from "../../../src/api/middleware/errorHandler.js"; -import ValidationReasons from "../../../src/api/middleware/validators/validationReasons.js"; -import base64url from "base64url"; import { DAY_TO_MS } from "../../utils/TimeConstants.js"; -import withGodToken from "../../utils/GodToken.js"; import CompanyApplication from "../../../src/models/CompanyApplication.js"; import Account from "../../../src/models/Account.js"; import hash from "../../../src/lib/passwordHashing.js"; @@ -31,7 +26,6 @@ describe("Using already created offer(s)", () => { ...params, }); - const test_agent = agent(); const test_user_admin = { email: "admin@email.com", @@ -152,229 +146,6 @@ describe("Using already created offer(s)", () => { Date.now = RealDateNow; }); - describe("queryToken validation", () => { - test("should fail if queryToken does not contain a valid id", async () => { - const queryToken = (new OfferService()).encodeQueryToken("123", 5, "publishDate", mockCurrentDate, false, "test", {}); - - const res = await request() - .get("/offers") - .query({ queryToken }); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); - expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); - expect(res.body.errors[0]).toHaveProperty("location", "query"); - }); - - test("should fail if the queryToken's offer does not exist", async () => { - const queryToken = (new OfferService()) - .encodeQueryToken("5facf0cdb8bc30016ee58952", 5, "publishDate", mockCurrentDate, false, "test", {}); - const res = await request() - .get("/offers") - .query({ queryToken }); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); - expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); - expect(res.body.errors[0]).toHaveProperty("location", "query"); - }); - - test("should fail if the queryToken's score is not a number", async () => { - const testOfferId = (await Offer.findOne({}))._id; - const queryToken = (new OfferService()) - .encodeQueryToken(testOfferId, "hello", "test", "test", false, "test", {}); - - const res = await request() - .get("/offers") - .query({ queryToken }); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); - expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); - expect(res.body.errors[0]).toHaveProperty("location", "query"); - }); - - test("should fail if the queryToken's score is negative", async () => { - const testOfferId = (await Offer.findOne({}))._id; - const queryToken = (new OfferService()) - .encodeQueryToken(testOfferId, -5, "publishDate", mockCurrentDate, false, "test", {}); - - const res = await request() - .get("/offers") - .query({ queryToken }); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); - expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); - expect(res.body.errors[0]).toHaveProperty("location", "query"); - }); - - test("should fail if the queryToken's value is present and score is missing", async () => { - const testOfferId = (await Offer.findOne({}))._id; - const queryToken = (new OfferService()) - .encodeQueryToken(testOfferId, undefined, "test", "test", false, "test", {}); - - const res = await request() - .get("/offers") - .query({ queryToken }); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); - expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); - expect(res.body.errors[0]).toHaveProperty("location", "query"); - }); - - test("should fail if the queryToken's score is present and value is missing", async () => { - const testOfferId = (await Offer.findOne({}))._id; - const queryToken = (new OfferService()) - .encodeQueryToken(testOfferId, 5, "publishDate", mockCurrentDate, false, undefined, {}); - - const res = await request() - .get("/offers") - .query({ queryToken }); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); - expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); - expect(res.body.errors[0]).toHaveProperty("location", "query"); - }); - - test("should fail if the queryToken's publishDate is not a date", async () => { - const testOfferId = (await Offer.findOne({}))._id; - const queryToken = base64url.encode(JSON.stringify({ - id: testOfferId, score: 5, sortField: "publishDate", sortValue: "help", sortDescending: true, value: 5 - })); - - const res = await request() - .get("/offers") - .query({ queryToken }); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); - expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); - expect(res.body.errors[0]).toHaveProperty("location", "query"); - }); - - test("should fail if the queryToken's publishEndDate is not a date", async () => { - const testOfferId = (await Offer.findOne({}))._id; - const queryToken = base64url.encode(JSON.stringify({ - id: testOfferId, score: 5, sortField: "publishEndDate", sortValue: "help", sortDescending: true, value: 5 - })); - - const res = await request() - .get("/offers") - .query({ queryToken }); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); - expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); - expect(res.body.errors[0]).toHaveProperty("location", "query"); - }); - - test("should fail if the queryToken's sortValue is missing", async () => { - const testOfferId = (await Offer.findOne({}))._id; - const queryToken = (new OfferService()) - .encodeQueryToken(testOfferId, 5, "test", undefined, true, undefined, {}); - - const res = await request() - .get("/offers") - .query({ queryToken }); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); - expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); - expect(res.body.errors[0]).toHaveProperty("location", "query"); - }); - - test("should fail if the queryToken's sortField is missing", async () => { - const testOfferId = (await Offer.findOne({}))._id; - const queryToken = (new OfferService()) - .encodeQueryToken(testOfferId, 5, undefined, "test", true, undefined, {}); - - const res = await request() - .get("/offers") - .query({ queryToken }); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); - expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); - expect(res.body.errors[0]).toHaveProperty("location", "query"); - }); - - test("should fail if the queryToken's sortDescending is missing", async () => { - const testOfferId = (await Offer.findOne({}))._id; - const queryToken = (new OfferService()) - .encodeQueryToken(testOfferId, 5, "test", "test", undefined, undefined, {}); - - const res = await request() - .get("/offers") - .query({ queryToken }); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.INVALID_QUERY_TOKEN); - expect(res.body.errors[0]).toHaveProperty("param", "queryToken"); - expect(res.body.errors[0]).toHaveProperty("location", "query"); - }); - - test("should succeed when the queryToken's value and score are missing", async () => { - const testOfferId = (await Offer.findOne({}))._id; - const queryToken = (new OfferService()) - .encodeQueryToken(testOfferId, undefined, "publishDate", mockCurrentDate, true, undefined, {}); - - const res = await request() - .get("/offers") - .query({ queryToken }); - - expect(res.status).toBe(HTTPStatus.OK); - }); - - test("should succeed when the queryToken's value is present and score is a valid number", async () => { - const testOfferId = (await Offer.findOne({}))._id; - const queryToken = (new OfferService()) - .encodeQueryToken(testOfferId, 5, "test", "test", false, "test", {}); - - const res = await request() - .get("/offers") - .query({ queryToken }); - - expect(res.status).toBe(HTTPStatus.OK); - }); - - test("should succeed when value is present and queryToken's score can be parsed as a number", async () => { - const testOfferId = (await Offer.findOne({}))._id; - const queryToken = (new OfferService()) - .encodeQueryToken(testOfferId, "3.5", "test", "test", false, "test", {}); - - const res = await request() - .get("/offers") - .query({ queryToken }); - - expect(res.status).toBe(HTTPStatus.OK); - }); - }); - describe("Only current offers are returned", () => { const expired_test_offer = generateTestOffer({ @@ -427,1719 +198,5 @@ describe("Using already created offer(s)", () => { expect(extracted_data).toContainEqual(prepared_test_offer); }); - - - test("should provide only current offer info (no expired or future offers with no value query)", async () => { - const res = await request() - .get("/offers"); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) - const extracted_data = res.body.results.map((elem) => { - delete elem["_id"]; - delete elem["__v"]; - delete elem["createdAt"]; - delete elem["updatedAt"]; - delete elem["score"]; - delete elem["queryToken"]; - return elem; - }); - const prepared_test_offer = { - ...test_offer, - isHidden: false, - owner: test_offer.owner.toString(), - - }; - - expect(extracted_data).toContainEqual(prepared_test_offer); - }); - - test("should provide only current offer info (no expired or future offers with some value query)", async () => { - const res = await request() - .get("/offers") - .query({ - value: "test", - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) - const extracted_data = res.body.results.map((elem) => { - delete elem["_id"]; - delete elem["__v"]; - delete elem["createdAt"]; - delete elem["updatedAt"]; - delete elem["score"]; - delete elem["queryToken"]; - return elem; - }); - const prepared_test_offer = { - ...test_offer, - isHidden: false, - owner: test_offer.owner.toString() - }; - - expect(extracted_data).toContainEqual(prepared_test_offer); - }); - - describe("When a limit is given", () => { - beforeAll(async () => { - // Add 2 more offers - await Offer.deleteMany({}); - await Offer.create([test_offer, future_test_offer, test_offer, test_offer]); - }); - - test("Only `limit` number of offers are returned", async () => { - const res = await request() - .get("/offers") - .query({ - limit: 2, - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - - // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) - const extracted_data = res.body.results.map((elem) => { - delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; - delete elem["updatedAt"]; delete elem["queryToken"]; - return elem; - }); - - const prepared_test_offer = { - ...test_offer, - isHidden: false, - owner: test_offer.owner.toString() - }; - - expect(extracted_data).toContainEqual(prepared_test_offer); - }); - }); - - describe("When queryToken is given", () => { - - beforeAll(async () => { - // Add another offer - await Offer.deleteMany({}); - await Offer.create([test_offer, { ...test_offer, jobType: "FULL-TIME" }, - expired_test_offer, future_test_offer]); - }); - - test("should fetch offers with the id greater than the one provided", async () => { - const res = await request() - .get("/offers") - .query({ limit: 1 }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - const res2 = await request() - .get("/offers") - .query({ queryToken: res.body.queryToken }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - - const offer = res2.body.results[0]; - expect(offer._id).not.toBe(res.body.results[0]._id); - }); - - test("should succeed if there are no more offers after the last one", async () => { - const res = await request() - .get("/offers"); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - - const res2 = await request() - .get("/offers") - .query({ queryToken: res.body.queryToken }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(0); - }); - - test("offers are returned according to filters", async () => { - const res = await request() - .get("/offers") - .query({ - publishDate: testPublishDate, - publishEndDate: testPublishEndDate, - jobType: "FULL-TIME" - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - expect(res.body.results[0].jobType).toBe("FULL-TIME"); - }); - - test("offers are returned according to filters when using queryToken", async () => { - const res = await request() - .get("/offers") - .query({ - publishDate: testPublishDate, - publishEndDate: testPublishEndDate, - fields: ["DEVOPS"], - limit: 1 - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - expect(res.body.results[0].fields).toContainEqual("DEVOPS"); - - const res2 = await request() - .get("/offers") - .query({ - queryToken: res.body.queryToken - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - expect(res2.body.results[0].fields).toContainEqual("DEVOPS"); - - const res3 = await request() - .get("/offers") - .query({ - publishDate: testPublishDate, - publishEndDate: testPublishEndDate, - jobType: "FULL-TIME" - }); - - expect(res3.status).toBe(HTTPStatus.OK); - expect(res3.body?.results).toHaveLength(1); - expect(res3.body.results[0].jobType).toBe("FULL-TIME"); - - const res4 = await request() - .get("/offers") - .query({ - queryToken: res3.body.queryToken - }); - - expect(res4.status).toBe(HTTPStatus.OK); - expect(res4.body?.results).toHaveLength(0); - }); - - describe("When offers have different publish dates", () => { - beforeAll(async () => { - Date.now = () => mockCurrentDate.getTime(); - - const least_recent_offer = generateTestOffer({ - "publishDate": (new Date(Date.now() - (2 * DAY_TO_MS))).toISOString(), - "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() - }); - - const middle_offer1 = generateTestOffer({ - "publishDate": (new Date(Date.now() - (DAY_TO_MS))).toISOString(), - "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() - }); - - const most_recent_offer = generateTestOffer({ - "publishDate": (new Date(Date.now())).toISOString(), - "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() - }); - - Date.now = RealDateNow; - - [least_recent_offer, middle_offer1, middle_offer1, most_recent_offer] - .forEach((offer) => { - offer.owner = test_company._id; - offer.ownerName = test_company.name; - offer.ownerLogo = test_company.logo; - }); - - await Offer.deleteMany({}); - await Offer.create([least_recent_offer, middle_offer1, middle_offer1, most_recent_offer]); - - await test_agent - .post("/auth/login") - .send({ - email: test_user_company.email, - password: test_user_company.password, - }); - }); - - afterAll(async () => { - await test_agent - .delete("/auth/login"); - await Offer.deleteMany({}); - await Offer.create([test_offer, { ...test_offer, jobType: "FULL-TIME" }, - expired_test_offer, future_test_offer]); - }); - - test("Offers should be sorted by publishDate in descending order and then by id", async () => { - const res = await test_agent - .get("/offers"); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body.results).toHaveLength(4); - - for (let i = 0; i < res.body.results.length - 1; i++) { - try { - expect((new Date(res.body.results[i].publishDate)).getTime()) - .toBeGreaterThan((new Date(res.body.results[i + 1].publishDate)).getTime()); - } catch { - expect(res.body.results[i].publishDate) - .toBe(res.body.results[i + 1].publishDate); - - expect(res.body.results[i]._id < res.body.results[i + 1]._id) - .toBeTruthy(); - } - } - }); - - test("Should return next most recent offer", async () => { - const res1 = await test_agent - .get("/offers") - .query({ - limit: 3 - }); - - expect(res1.status).toBe(HTTPStatus.OK); - expect(res1.body.results).toHaveLength(3); - - const res2 = await test_agent - .get("/offers") - .query({ - queryToken: res1.body.queryToken, - limit: 1 - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body.results).toHaveLength(1); - expect((new Date(res2.body.results[0].publishDate)).getTime()) - .toBeLessThan((new Date(res1.body.results[2].publishDate)).getTime()); - }); - - test("Should return next offer that is as recent but with a higher id", async () => { - const res1 = await test_agent - .get("/offers") - .query({ - limit: 2 - }); - - expect(res1.status).toBe(HTTPStatus.OK); - expect(res1.body.results).toHaveLength(2); - - const res2 = await test_agent - .get("/offers") - .query({ - queryToken: res1.body.queryToken, - limit: 1 - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body.results).toHaveLength(1); - expect(res2.body.results[0]._id > res1.body.results[1]._id) - .toBeTruthy(); - }); - }); - }); - - describe("When showHidden is active", () => { - - beforeAll(async () => { - // Add 1 hidden offer - await Offer.deleteMany({}); - await Offer.create([test_offer, { ...test_offer, isHidden: true }]); - - }); - - test("Should not return hidden offers by default", async () => { - await test_agent - .post("/auth/login") - .send({ - email: test_user_company.email, - password: test_user_company.password, - }); - - const res = await test_agent - .get("/offers"); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) - const extracted_data = res.body.results.map((elem) => { - delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; - delete elem["updatedAt"]; delete elem["queryToken"]; - return elem; - }); - - const prepared_test_offer = { - ...test_offer, - isHidden: false, - owner: test_offer.owner.toString() - }; - - expect(extracted_data).toContainEqual(prepared_test_offer); - }); - - test("Only admins can use showHidden", async () => { - await test_agent - .post("/auth/login") - .send({ - email: test_user_company.email, - password: test_user_company.password, - }); - - const res = await test_agent - .get("/offers") - .query({ - showHidden: true, - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) - const extracted_data = res.body.results.map((elem) => { - delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; - delete elem["updatedAt"]; delete elem["queryToken"]; - return elem; - }); - - const prepared_test_offer = { - ...test_offer, - isHidden: false, - owner: test_offer.owner.toString() - }; - - expect(extracted_data).toContainEqual(prepared_test_offer); - }); - - test("Only admins can use showHidden (with admin)", async () => { - await test_agent - .post("/auth/login") - .send({ - email: test_user_admin.email, - password: test_user_admin.password, - }); - - const res = await test_agent - .get("/offers") - .query({ - showHidden: true, - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - - // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) - const extracted_data = res.body.results.map((elem) => { - delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; - delete elem["updatedAt"]; delete elem["queryToken"]; - return elem; - }); - - const prepared_test_offer = { - ...test_offer, - isHidden: false, - owner: test_offer.owner.toString() - }; - - expect(extracted_data).toContainEqual(prepared_test_offer); - }); - }); - - describe("showAdminReason", () => { - - beforeAll(async () => { - await Offer.deleteMany({}); - const test_offers = []; - - for (let i = 0; i < 5; i++) - test_offers.push( - { - ...test_offer, - isHidden: true, - hiddenReason: "ADMIN_REQUEST", - adminReason: "my_reason" - }); - - await Offer.create(test_offers); - }); - - afterEach(async () => { - await test_agent.del("/auth/login"); - }); - - test("should return adminReason if logged as admin", async () => { - - await test_agent - .post("/auth/login") - .send(test_user_admin) - .expect(HTTPStatus.OK); - - const res = await test_agent - .get("/offers") - .query({ - showHidden: true, - }); - - expect(res.status).toBe(HTTPStatus.OK); - - const extracted_data = res.body.results.map((elem) => elem["adminReason"]); - - const expected_data = ["my_reason", "my_reason", "my_reason", "my_reason", "my_reason"]; - - expect(extracted_data).toEqual(expected_data); - }); - - test("should return adminReason if god token is sent", async () => { - - const res = await test_agent - .get("/offers") - .query({ - showHidden: true, - }) - .send(withGodToken()); - - expect(res.status).toBe(HTTPStatus.OK); - - const extracted_data = res.body.results.map((elem) => elem["adminReason"]); - - const expected_data = ["my_reason", "my_reason", "my_reason", "my_reason", "my_reason"]; - - expect(extracted_data).toEqual(expected_data); - }); - - test("should not return adminReason if logged as company", async () => { - - await test_agent - .post("/auth/login") - .send(test_user_company) - .expect(HTTPStatus.OK); - - const res = await test_agent - .get("/offers"); - - expect(res.status).toBe(HTTPStatus.OK); - - const extracted_data = res.body.results.map((elem) => elem["adminReason"]); - - const expected_data = []; - - expect(extracted_data).toEqual(expected_data); - - }); - - test("should not return adminReason if not logged in", async () => { - - const res = await test_agent - .get("/offers"); - - expect(res.status).toBe(HTTPStatus.OK); - - const extracted_data = res.body.results.map((elem) => elem["adminReason"]); - - const expected_data = []; - - expect(extracted_data).toEqual(expected_data); - - }); - }); - }); - - describe("Full text search", () => { - - let portoFrontend; - let portoBackend; - let lisboaBackend; - let niaefeupOffer; - - beforeAll(async () => { - portoFrontend = { - ...test_offer, - title: "This offer is from Porto", - location: "Porto", - jobType: "FULL-TIME", - fields: ["FRONTEND", "OTHER"], - jobMinDuration: 3, - jobMaxDuration: 6 - }; - portoBackend = { - ...test_offer, - location: "Porto", - fields: ["BACKEND", "OTHER"], - jobMinDuration: 2, - jobMaxDuration: 4 - }; - lisboaBackend = { - ...test_offer, - location: "Lisboa", - fields: ["BACKEND", "DEVOPS"] - }; - niaefeupOffer = { - ...test_offer, - location: "FEUP", - fields: ["BLOCKCHAIN", "OTHER"], - ownerName: "NIAEFEUP" - }; - await Offer.deleteMany({}); - await Offer.create([portoBackend, portoFrontend, lisboaBackend, niaefeupOffer]); - }); - - test("should return porto offers", async () => { - - const res = await request() - .get("/offers") - .query({ - value: "porto" - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - - // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) - const extracted_data = res.body.results.map((elem) => { - delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; - delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; - return elem; - }); - - // eslint-disable-next-line no-unused-vars - const expected_offers = [portoBackend, portoFrontend].map(({ owner, ...offer }) => ({ - ...offer, - isHidden: false, - owner: owner.toString() - })); - - expected_offers.forEach((expected) => { - expect(extracted_data).toContainEqual(expected); - }); - }); - - test("should return niaefeup (company) offers", async () => { - - const res = await request() - .get("/offers") - .query({ - value: "niaefeup" - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) - const extracted_data = res.body.results.map((elem) => { - delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; - delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; - return elem; - }); - - const prepared_test_offer = { - ...niaefeupOffer, - isHidden: false, - owner: niaefeupOffer.owner.toString() - }; - - expect(extracted_data).toContainEqual(prepared_test_offer); - }); - - test("should return porto offers in order", async () => { - - const res = await request() - .get("/offers") - .query({ - value: "porto frontend" - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - - // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) - const extracted_data = res.body.results.map((elem) => { - delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; - delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; - return elem; - }); - - // eslint-disable-next-line no-unused-vars - const expected_offers = [portoFrontend, portoBackend].map(({ owner, ...offer }) => ({ - ...offer, - isHidden: false, - owner: owner.toString() - })); - - expected_offers.forEach((expected, i) => { - expect(extracted_data[i]).toEqual(expected); - }); - }); - - test("should return porto offers for FULL-TIME", async () => { - - const res = await request() - .get("/offers") - .query({ - value: "porto", - jobType: "FULL-TIME" - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) - const extracted_data = res.body.results.map((elem) => { - delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; - delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; - return elem; - }); - - const prepared_test_offer = { - ...portoFrontend, - isHidden: false, - owner: portoFrontend.owner.toString() - }; - - expect(extracted_data).toContainEqual(prepared_test_offer); - }); - - test("should return porto offers with React", async () => { - - const res = await request() - .get("/offers") - .query({ - value: "porto", - technologies: ["React"] - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - - // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) - const extracted_data = res.body.results.map((elem) => { - delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; - delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; - return elem; - }); - - // eslint-disable-next-line no-unused-vars - const expected_offers = [portoFrontend, portoBackend].map(({ owner, ...offer }) => ({ - ...offer, - isHidden: false, - owner: owner.toString() - })); - - expected_offers.forEach((expected) => { - expect(extracted_data).toContainEqual(expected); - }); - }); - - test("should return offers with DEVOPS", async () => { - - const res = await request() - .get("/offers") - .query({ - fields: ["DEVOPS"] - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) - const extracted_data = res.body.results.map((elem) => { - delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; - delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; - return elem; - }); - - const prepared_test_offer = { - ...lisboaBackend, - isHidden: false, - owner: lisboaBackend.owner.toString() - }; - - expect(extracted_data).toContainEqual(prepared_test_offer); - }); - - test("should return porto offers with min duration of 2", async () => { - - const res = await request() - .get("/offers") - .query({ - value: "porto", - jobMinDuration: 2 - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - - // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) - const extracted_data = res.body.results.map((elem) => { - delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; - delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; - return elem; - }); - - // eslint-disable-next-line no-unused-vars - const expected_offers = [portoFrontend, portoBackend].map(({ owner, ...offer }) => ({ - ...offer, - isHidden: false, - owner: owner.toString() - })); - - expected_offers.forEach((expected) => { - expect(extracted_data).toContainEqual(expected); - }); - }); - - test("should return porto offers with min duration of 2 and max duration of 4", async () => { - - // This test should include the 3-6 offer as well, since [3,6] intersects [2,4] - - const res = await request() - .get("/offers") - .query({ - value: "porto", - jobMinDuration: 2, - jobMaxDuration: 4 - }); - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - - // Necessary because jest matchers appear to not be working (expect.any(Number), expect.anthing(), etc) - const extracted_data = res.body.results.map((elem) => { - delete elem["_id"]; delete elem["__v"]; delete elem["createdAt"]; - delete elem["updatedAt"]; delete elem["score"]; delete elem["queryToken"]; - return elem; - }); - - // eslint-disable-next-line no-unused-vars - const expected_offers = [portoBackend, portoFrontend].map(({ owner, ...offer }) => ({ - ...offer, - isHidden: false, - owner: owner.toString() - })); - - expected_offers.forEach((expected) => { - expect(extracted_data).toContainEqual(expected); - }); - }); - - describe("When queryToken and value are given", () => { - - test("should return next matching offer with lower score", async () => { - const res = await request() - .get("/offers") - .query({ - value: "porto", - limit: 1 - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - expect(res.body.results[0].title).toEqual(portoFrontend.title); - - const res2 = await request() - .get("/offers") - .query({ - value: "porto", - queryToken: res.body.queryToken - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - expect(res2.body.results[0].title).toEqual(portoBackend.title); - }); - - test("should return next matching offer with the same score", async () => { - const res = await request() - .get("/offers") - .query({ - value: "backend", - limit: 1 - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - const res2 = await request() - .get("/offers") - .query({ - value: "backend", - queryToken: res.body.queryToken - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - }); - - describe("With offers with different publish dates", () => { - beforeAll(async () => { - Date.now = () => mockCurrentDate.getTime(); - - const bestScoreMostRecent = { - ...test_offer, - title: "This offer is from Porto", - "publishDate": (new Date(Date.now() - (DAY_TO_MS))).toISOString(), - "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() - }; - - const bestScoreLeastRecent = { - ...test_offer, - title: "This offer is from Porto", - "publishDate": (new Date(Date.now() - (2 * DAY_TO_MS))).toISOString(), - "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() - }; - - const worstScore = { - ...test_offer, - title: "This offer is from Braga", - location: "Porto", - "publishDate": (new Date(Date.now() - (DAY_TO_MS))).toISOString(), - "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() - }; - - Date.now = RealDateNow; - - await Offer.deleteMany({}); - await Offer.create([bestScoreMostRecent, bestScoreMostRecent, bestScoreLeastRecent, worstScore, worstScore]); - - await test_agent - .post("/auth/login") - .send({ - email: test_user_company.email, - password: test_user_company.password, - }); - }); - - afterAll(async () => { - await Offer.deleteMany({}); - await Offer.create([portoBackend, portoFrontend, lisboaBackend, niaefeupOffer]); - await test_agent - .delete("/auth/login"); - }); - - test("Offers should be ordered by score, publishDate and id in that order", async () => { - const res = await test_agent - .get("/offers") - .query({ - value: "Porto" - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body.results).toHaveLength(5); - - for (let i = 0; i < res.body.results.length - 1; i++) { - try { - expect(Number(res.body.results[i].score)) - .toBeGreaterThan(Number(res.body.results[i + 1].score)); - } catch { - try { - expect(res.body.results[i].score) - .toBe(res.body.results[i + 1].score); - expect((new Date(res.body.results[i].publishDate)).getTime()) - .toBeGreaterThan((new Date(res.body.results[i + 1].publishDate)).getTime()); - } catch { - expect(res.body.results[i].score) - .toBe(res.body.results[i + 1].score); - expect(res.body.results[i].publishDate) - .toBe(res.body.results[i + 1].publishDate); - - expect(res.body.results[i]._id < res.body.results[i + 1]._id) - .toBeTruthy(); - } - } - } - }); - - test("Should return next offer with less score", async () => { - const res1 = await test_agent - .get("/offers") - .query({ - value: "Porto", - limit: 3 - }); - - expect(res1.status).toBe(HTTPStatus.OK); - expect(res1.body.results).toHaveLength(3); - - const res2 = await test_agent - .get("/offers") - .query({ - queryToken: res1.body.queryToken, - limit: 1 - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body.results).toHaveLength(1); - expect(Number(res2.body.results[0].score)) - .toBeLessThan(Number(res1.body.results[2].score)); - }); - - - test("Should return next offer with same score but least recent", async () => { - const res1 = await test_agent - .get("/offers") - .query({ - value: "Porto", - limit: 2 - }); - - expect(res1.status).toBe(HTTPStatus.OK); - expect(res1.body.results).toHaveLength(2); - - const res2 = await test_agent - .get("/offers") - .query({ - queryToken: res1.body.queryToken, - limit: 1 - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body.results).toHaveLength(1); - expect((new Date(res2.body.results[0].publishDate)).getTime()) - .toBeLessThan((new Date(res1.body.results[1].publishDate)).getTime()); - }); - - test("Should return next offer with same score and publishDate but higher id", async () => { - const res1 = await test_agent - .get("/offers") - .query({ - value: "Porto", - limit: 4 - }); - - expect(res1.status).toBe(HTTPStatus.OK); - expect(res1.body.results).toHaveLength(4); - - const res2 = await test_agent - .get("/offers") - .query({ - queryToken: res1.body.queryToken, - limit: 1 - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body.results).toHaveLength(1); - - expect(res2.body.results[0]._id > res1.body.results[3]._id) - .toBeTruthy(); - }); - - test("Should succeed if there are no more offers after the last one", async () => { - const res1 = await test_agent - .get("/offers") - .query({ - value: "Porto" - }); - - expect(res1.status).toBe(HTTPStatus.OK); - expect(res1.body.results).toHaveLength(5); - - const res2 = await test_agent - .get("/offers") - .query({ - queryToken: res1.body.queryToken - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body.results).toHaveLength(0); - }); - }); - - describe("With not current offers", () => { - - const expired_test_offer = generateTestOffer({ - "publishDate": (new Date(Date.now() - (2 * DAY_TO_MS))).toISOString(), - "publishEndDate": (new Date(Date.now() - (DAY_TO_MS))).toISOString() - }); - const future_test_offer = generateTestOffer({ - "publishDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString(), - "publishEndDate": (new Date(Date.now() + (2 * DAY_TO_MS))).toISOString() - }); - - beforeAll(async () => { - - [future_test_offer, expired_test_offer] - .forEach((offer) => { - offer.owner = test_company._id; - offer.ownerName = test_company.name; - offer.ownerLogo = test_company.logo; - }); - - await Offer.create([expired_test_offer, future_test_offer]); - }); - - afterAll(async () => { - await Offer.deleteOne(future_test_offer); - await Offer.deleteOne(expired_test_offer); - }); - - test("should provide only current offers", async () => { - const res = await request() - .get("/offers") - .query({ - value: "porto", - limit: 1 - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - const res2 = await request() - .get("/offers") - .query({ - value: "porto", - queryToken: res.body.queryToken - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - - res2.body.results.forEach((offer) => { - expect(offer.publishDate <= new Date(Date.now()).toISOString()).toBeTruthy(); - expect(offer.publishEndDate >= new Date(Date.now()).toISOString()).toBeTruthy(); - }); - }); - }); - - describe("When queryToken and value are provided and showHidden is active", () => { - - beforeAll(async () => { - await Offer.create({ - ...portoFrontend, - isHidden: true, - title: "This offer is hidden" - }); - }); - - afterAll(async () => { - await Offer.deleteOne({ isHidden: true }); - }); - - test("should not return hidden offers by default", async () => { - const res = await request() - .get("/offers") - .query({ - value: "porto", - limit: 1 - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - const res2 = await request() - .get("/offers") - .query({ - value: "porto", - queryToken: res.body.queryToken - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - - res2.body.results.forEach((offer) => { - expect(offer.isHidden).toBeFalsy(); - }); - }); - - test("companies should not see their hidden offers", async () => { - await test_agent - .post("/auth/login") - .send(test_user_company) - .expect(HTTPStatus.OK); - - const res = await test_agent - .get("/offers") - .query({ - value: "porto", - showHidden: true, - limit: 1 - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - const res2 = await test_agent - .get("/offers") - .query({ - value: "porto", - queryToken: res.body.queryToken - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - - res2.body.results.forEach((offer) => { - expect(offer.isHidden).toBeFalsy(); - }); - }); - - test("admins should see hidden offers", async () => { - await test_agent - .post("/auth/login") - .send(test_user_admin) - .expect(HTTPStatus.OK); - - const res = await test_agent - .get("/offers") - .query({ - value: "porto", - showHidden: true, - limit: 1 - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - const res2 = await test_agent - .get("/offers") - .query({ - value: "porto", - showHidden: true, - queryToken: res.body.queryToken - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(2); - }); - - test("should see hidden offers if god token is sent", async () => { - const res = await test_agent - .get("/offers") - .query({ - value: "porto", - showHidden: true, - limit: 1 - }) - .send(withGodToken()); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - const res2 = await test_agent - .get("/offers") - .query({ - value: "porto", - showHidden: true, - queryToken: res.body.queryToken - }) - .send(withGodToken()); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(2); - }); - }); - - describe("When queryToken and value are provided and adminReason is set", () => { - beforeAll(async () => { - await Offer.create({ - ...portoFrontend, - title: "This offer was hidden by an admin", - isHidden: true, - hiddenReason: "ADMIN_REQUEST", - adminReason: "test_reason" - }); - }); - - afterAll(async () => { - await Offer.deleteOne({ isHidden: true }); - }); - - test("should return adminReason if logged in as admin", async () => { - await test_agent - .post("/auth/login") - .send(test_user_admin) - .expect(HTTPStatus.OK); - - const res = await test_agent - .get("/offers") - .query({ - value: "porto", - showHidden: true, - limit: 1 - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - const res2 = await test_agent - .get("/offers") - .query({ - value: "porto", - showHidden: true, - queryToken: res.body.queryToken - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(2); - - res2.body.results.filter((offer) => offer.isHidden).forEach((offer) => { - expect(offer.hiddenReason).toBe("ADMIN_REQUEST"); - expect(offer.adminReason).toBe("test_reason"); - }); - }); - - test("should return adminReason if god token is sent", async () => { - const res = await test_agent - .get("/offers") - .query({ - value: "porto", - showHidden: true, - limit: 1 - }) - .send(withGodToken()); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - - const res2 = await test_agent - .get("/offers") - .query({ - value: "porto", - showHidden: true, - queryToken: res.body.queryToken - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(2); - - res2.body.results.filter((offer) => offer.isHidden).forEach((offer) => { - expect(offer.hiddenReason).toBe("ADMIN_REQUEST"); - expect(offer.adminReason).toBe("test_reason"); - }); - }); - - test("companies should not see admin reason for their own offers", async () => { - await test_agent - .post("/auth/login") - .send(test_user_company) - .expect(HTTPStatus.OK); - - const res = await test_agent - .get("/offers") - .query({ - value: "porto", - showHidden: true, - limit: 1 - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - expect(res.body.results[0].adminReason).toBeUndefined(); - - const res2 = await test_agent - .get("/offers") - .query({ - value: "porto", - showHidden: true, - queryToken: res.body.queryToken - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - res2.body.results.forEach((offer) => { - expect(offer.adminReason).toBeUndefined(); - }); - }); - - test("should not return admin reason if not logged in", async () => { - const res = await test_agent - .get("/offers") - .query({ - value: "porto", - showHidden: true, - limit: 1 - }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - expect(res.body.results[0].adminReason).toBeUndefined(); - - const res2 = await test_agent - .get("/offers") - .query({ - value: "porto", - showHidden: true, - queryToken: res.body.queryToken - }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - res2.body.results.forEach((offer) => { - expect(offer.adminReason).toBeUndefined(); - }); - }); - }); - }); - }); - - describe("Offer requirements", () => { - - beforeAll(async () => { - await Offer.deleteMany(); - await Offer.create(test_offer); - }); - - test("should return an array of requirements", async () => { - - const res = await request() - .get("/offers"); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - expect(res.body.results[0].requirements).toEqual(test_offer.requirements); - }); - }); - - describe("Offer sorting", () => { - beforeAll(async () => { - await Offer.deleteMany(); - await Offer.create(test_offer); - - await Offer.create({ - ...test_offer, - title: "Amazing offer", - publishDate: "2019-11-23T00:00:00.000Z", - publishEndDate: "2019-11-29T00:00:00.000Z", - description: "Ability to have an incredible job", - jobType: "OTHER", - location: "Aveiro", - vacancies: 1, - ownerName: "Awesome Company", - }); - }); - - afterAll(async () => { - await Offer.deleteMany({}); - }); - - test("should sort by publishDate by default", async () => { - const res = await request() - .get("/offers"); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe("Amazing offer"); - expect(res.body.results[1].title).toBe(test_offer.title); - }); - - test("should sort by title ascending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "title" }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe("Amazing offer"); - expect(res.body.results[1].title).toBe(test_offer.title); - }); - - test("should sort by title descending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "title", descending: true }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe(test_offer.title); - expect(res.body.results[1].title).toBe("Amazing offer"); - }); - - test("should sort by publishDate ascending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "publishDate" }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe(test_offer.title); - expect(res.body.results[1].title).toBe("Amazing offer"); - }); - - test("should sort by publishDate descending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "publishDate", descending: true }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe("Amazing offer"); - expect(res.body.results[1].title).toBe(test_offer.title); - }); - - test("should sort by publishEndDate ascending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "publishEndDate" }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe(test_offer.title); - expect(res.body.results[1].title).toBe("Amazing offer"); - }); - - test("should sort by publishEndDate descending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "publishEndDate", descending: true }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe("Amazing offer"); - expect(res.body.results[1].title).toBe(test_offer.title); - }); - - test("should sort by description ascending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "description" }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe("Amazing offer"); - expect(res.body.results[1].title).toBe(test_offer.title); - }); - - test("should sort by description descending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "description", descending: true }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe(test_offer.title); - expect(res.body.results[1].title).toBe("Amazing offer"); - }); - - test("should sort by jobType ascending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "jobType" }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe("Amazing offer"); - expect(res.body.results[1].title).toBe(test_offer.title); - }); - - test("should sort by jobType descending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "jobType", descending: true }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe(test_offer.title); - expect(res.body.results[1].title).toBe("Amazing offer"); - }); - - test("should sort by location ascending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "location" }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe("Amazing offer"); - expect(res.body.results[1].title).toBe(test_offer.title); - }); - - test("should sort by location descending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "location", descending: true }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe(test_offer.title); - expect(res.body.results[1].title).toBe("Amazing offer"); - }); - - test("should sort by vacancies ascending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "vacancies" }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe("Amazing offer"); - expect(res.body.results[1].title).toBe(test_offer.title); - }); - - test("should sort by vacancies descending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "vacancies", descending: true }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe(test_offer.title); - expect(res.body.results[1].title).toBe("Amazing offer"); - }); - - test("should sort by ownerName ascending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "ownerName" }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe("Amazing offer"); - expect(res.body.results[1].title).toBe(test_offer.title); - }); - - test("should sort by ownerName descending", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "ownerName", descending: true }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(2); - expect(res.body.results[0].title).toBe(test_offer.title); - expect(res.body.results[1].title).toBe("Amazing offer"); - }); - - describe("Using pagination", () => { - beforeAll(async () => { - await Offer.deleteMany(); - await Offer.create(test_offer); - - await Offer.create({ - ...test_offer, - title: "Amazing offer", - publishDate: "2019-11-23T00:00:00.000Z", - publishEndDate: "2019-11-29T00:00:00.000Z", - description: "Ability to have an incredible job", - jobType: "OTHER", - location: "Aveiro", - ownerName: "Awesome Company", - vacancies: 3, - }); - }); - - afterAll(async () => { - await Offer.deleteMany({}); - }); - - test("should sort by title in multiple pages", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "title", limit: 1 }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - expect(res.body.results[0].title).toBe("Amazing offer"); - - const res2 = await request() - .get("/offers") - .query({ limit: 1, queryToken: res.body.queryToken }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - expect(res2.body.results[0].title).toBe(test_offer.title); - }); - - test("should sort by publishEndDate in multiple pages", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "publishEndDate", limit: 1 }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - expect(res.body.results[0].title).toBe(test_offer.title); - - const res2 = await request() - .get("/offers") - .query({ limit: 1, queryToken: res.body.queryToken }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - expect(res2.body.results[0].title).toBe("Amazing offer"); - }); - - test("should sort by description in multiple pages", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "description", limit: 1 }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - expect(res.body.results[0].title).toBe("Amazing offer"); - - const res2 = await request() - .get("/offers") - .query({ limit: 1, queryToken: res.body.queryToken }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - expect(res2.body.results[0].title).toBe(test_offer.title); - }); - - test("should sort by jobType in multiple pages", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "jobType", limit: 1 }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - expect(res.body.results[0].title).toBe("Amazing offer"); - - const res2 = await request() - .get("/offers") - .query({ limit: 1, queryToken: res.body.queryToken }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - expect(res2.body.results[0].title).toBe(test_offer.title); - }); - - test("should sort by location in multiple pages", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "location", limit: 1 }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - expect(res.body.results[0].title).toBe("Amazing offer"); - - const res2 = await request() - .get("/offers") - .query({ limit: 1, queryToken: res.body.queryToken }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - expect(res2.body.results[0].title).toBe(test_offer.title); - }); - - test("should sort by vacancies in multiple pages", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "vacancies", limit: 1 }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - expect(res.body.results[0].title).toBe(test_offer.title); - - const res2 = await request() - .get("/offers") - .query({ limit: 1, queryToken: res.body.queryToken }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - expect(res2.body.results[0].title).toBe("Amazing offer"); - }); - - test("should sort by ownerName in multiple pages", async () => { - const res = await request() - .get("/offers") - .query({ sortBy: "ownerName", limit: 1 }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body?.results).toHaveLength(1); - expect(res.body.results[0].title).toBe("Amazing offer"); - - const res2 = await request() - .get("/offers") - .query({ limit: 1, queryToken: res.body.queryToken }); - - expect(res2.status).toBe(HTTPStatus.OK); - expect(res2.body?.results).toHaveLength(1); - expect(res2.body.results[0].title).toBe(test_offer.title); - }); - }); }); }); diff --git a/test/end-to-end/offers/new.js b/test/end-to-end/offers/new.js index 8f7229af..29ac2094 100644 --- a/test/end-to-end/offers/new.js +++ b/test/end-to-end/offers/new.js @@ -3,20 +3,11 @@ import Company from "../../../src/models/Company.js"; import Account from "../../../src/models/Account.js"; import hash from "../../../src/lib/passwordHashing.js"; import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js"; -import ValidationReasons from "../../../src/api/middleware/validators/validationReasons.js"; -import { ErrorTypes } from "../../../src/api/middleware/errorHandler.js"; import withGodToken from "../../utils/GodToken.js"; -import ValidatorTester from "../../utils/ValidatorTester.js"; -import OfferConstants from "../../../src/models/constants/Offer.js"; -import JobTypes from "../../../src/models/constants/JobTypes.js"; -import * as FieldConstants from "../../../src/models/constants/FieldTypes.js"; -import * as TechnologyConstants from "../../../src/models/constants/TechnologyTypes.js"; import Offer from "../../../src/models/Offer.js"; -import { MONTH_IN_MS, OFFER_MAX_LIFETIME_MONTHS } from "../../../src/models/constants/TimeConstants.js"; -import CompanyConstants from "../../../src/models/constants/Company.js"; import CompanyApplication from "../../../src/models/CompanyApplication.js"; -describe("Offer endpoint tests", () => { +describe("POST /offers/new", () => { const generateTestOffer = (params) => ({ title: "Test Offer", publishDate: (new Date(Date.now())).toISOString(), @@ -38,7 +29,6 @@ describe("Offer endpoint tests", () => { let test_company, approved_test_company; - const test_agent = agent(); const test_user_admin = { email: "admin@email.com", @@ -123,934 +113,30 @@ describe("Offer endpoint tests", () => { await CompanyApplication.deleteMany({}); }); - describe("POST /offers", () => { - - describe("Authentication", () => { - - describe("creating offers requires company account or admin account (without god token)", () => { - test("should fail if not logged in", async () => { - const res = await request() - .post("/offers/new") - .send({}); - - expect(res.status).toBe(HTTPStatus.UNAUTHORIZED); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors).toContainEqual({ msg: ValidationReasons.INSUFFICIENT_PERMISSIONS }); - }); - - test("should fail if not logged in, even if target owner is specified", async () => { - const params = { owner: test_company._id }; - const offer = generateTestOffer(params); - - const res = await request() - .post("/offers/new") - .send(offer); - - expect(res.status).toBe(HTTPStatus.UNAUTHORIZED); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors).toContainEqual({ msg: ValidationReasons.INSUFFICIENT_PERMISSIONS }); - }); - - test("should succeed if logged to admin account", async () => { - // Login - await test_agent - .post("/auth/login") - .send(test_user_admin) - .expect(200); - - const params = { owner: test_company._id }; - const offer = generateTestOffer(params); - const res = await test_agent - .post("/offers/new") - .send(offer); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body).toHaveProperty("title", offer.title); - expect(res.body).toHaveProperty("description", offer.description); - expect(res.body).toHaveProperty("location", offer.location); - }); - - test("should create offer if logged in to company account", async () => { - - // Login - const offer = { ...generateTestOffer() }; - await test_agent - .post("/auth/login") - .send(test_user_company) - .expect(200); - - const res = await test_agent - .post("/offers/new") - .send({ ...offer }); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body).toHaveProperty("title", offer.title); - expect(res.body).toHaveProperty("description", offer.description); - expect(res.body).toHaveProperty("location", offer.location); - expect(res.body).toHaveProperty("owner", test_company._id.toString()); - expect(res.body).toHaveProperty("ownerName", test_company.name); - expect(res.body).toHaveProperty("ownerLogo", test_company.logo); - }); - }); - - describe("creating offers requires god permissions", () => { - test("should fail when god token not provided", async () => { - const res = await request() - .post("/offers/new") - .send({}); - - expect(res.status).toBe(HTTPStatus.UNAUTHORIZED); - expect(res.body).toHaveProperty("error_code", ErrorTypes.FORBIDDEN); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors).toContainEqual({ msg: ValidationReasons.INSUFFICIENT_PERMISSIONS }); - }); - - test("should fail when god token is incorrect", async () => { - const res = await request() - .post("/offers/new") - .send({ - god_token: "NotAValidGodToken!!12345", - }); - - expect(res.status).toBe(HTTPStatus.UNAUTHORIZED); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors).toContainEqual({ msg: ValidationReasons.INSUFFICIENT_PERMISSIONS }); - }); - - test("should fail when god token is correct but owner doesn't exist", async () => { - const params = { ...generateTestOffer(), owner: "invalidowner" }; - const res = await request() - .post("/offers/new") - .send(withGodToken(params)); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body.errors).toContainEqual({ - value: "invalidowner", - location: "body", - msg: ValidationReasons.COMPANY_NOT_FOUND("invalidowner"), - param: "owner", - }); - - }); - - test("should succeed when god token is correct and owner exists", async () => { - const offer = generateTestOffer(); - const params = { ...offer, owner: test_company._id }; - const res = await request() - .post("/offers/new") - .send(withGodToken(params)); - - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body).toHaveProperty("title", offer.title); - expect(res.body).toHaveProperty("description", offer.description); - expect(res.body).toHaveProperty("location", offer.location); - }); - }); - }); - - const EndpointValidatorTester = ValidatorTester((params) => request().post("/offers/new").send(withGodToken(params))); - const BodyValidatorTester = EndpointValidatorTester("body"); - - describe("Input Validation", () => { - describe("title", () => { - const FieldValidatorTester = BodyValidatorTester("title"); - FieldValidatorTester.isRequired(); - FieldValidatorTester.mustBeString(); - FieldValidatorTester.hasMinLength(OfferConstants.title.min_length); - FieldValidatorTester.hasMaxLength(OfferConstants.title.max_length); - }); - - describe("publishDate", () => { - const FieldValidatorTester = BodyValidatorTester("publishDate"); - FieldValidatorTester.mustBeDate(); - FieldValidatorTester.mustBeFuture(); - }); - - describe("publishEndDate", () => { - const FieldValidatorTester = BodyValidatorTester("publishEndDate"); - FieldValidatorTester.isRequired(); - FieldValidatorTester.mustBeDate(); - FieldValidatorTester.mustBeFuture(); - FieldValidatorTester.mustBeAfter("publishDate"); - }); - - describe("jobMinDuration", () => { - const FieldValidatorTester = BodyValidatorTester("jobMinDuration"); - FieldValidatorTester.isRequired(); - FieldValidatorTester.mustBeNumber(); - }); - - describe("jobMaxDuration", () => { - const FieldValidatorTester = BodyValidatorTester("jobMaxDuration"); - FieldValidatorTester.isRequired(); - FieldValidatorTester.mustBeNumber(); - FieldValidatorTester.mustBeGreaterThanOrEqualToField("jobMinDuration"); - }); - - describe("jobStartDate", () => { - const FieldValidatorTester = BodyValidatorTester("jobStartDate"); - FieldValidatorTester.mustBeDate(); - }); - - describe("description", () => { - const FieldValidatorTester = BodyValidatorTester("description"); - FieldValidatorTester.isRequired(); - FieldValidatorTester.mustBeString(); - FieldValidatorTester.hasMaxLength(OfferConstants.description.max_length); - }); - - describe("contacts", () => { - const FieldValidatorTester = BodyValidatorTester("contacts"); - FieldValidatorTester.isRequired(); - FieldValidatorTester.mustHaveAtLeast(1); - }); - - describe("isPaid", () => { - const FieldValidatorTester = BodyValidatorTester("isPaid"); - FieldValidatorTester.mustBeBoolean(); - }); - - describe("vacancies", () => { - const FieldValidatorTester = BodyValidatorTester("vacancies"); - FieldValidatorTester.mustBeGreaterThanOrEqualTo(OfferConstants.vacancies.min); - }); - - describe("jobType", () => { - const FieldValidatorTester = BodyValidatorTester("jobType"); - FieldValidatorTester.isRequired(); - FieldValidatorTester.mustBeString(); - FieldValidatorTester.mustBeInArray(JobTypes); - }); - - describe("fields", () => { - const FieldValidatorTester = BodyValidatorTester("fields"); - FieldValidatorTester.isRequired(); - FieldValidatorTester.mustBeArrayBetween(FieldConstants.MIN_FIELDS, FieldConstants.MAX_FIELDS); - FieldValidatorTester.mustHaveValuesInRange(FieldConstants.FieldTypes, FieldConstants.MIN_FIELDS + 1); - }); - - describe("technologies", () => { - const FieldValidatorTester = BodyValidatorTester("technologies"); - FieldValidatorTester.isRequired(); - FieldValidatorTester.mustBeArrayBetween(TechnologyConstants.MIN_TECHNOLOGIES, TechnologyConstants.MAX_TECHNOLOGIES); - FieldValidatorTester.mustHaveValuesInRange(TechnologyConstants.TechnologyTypes, TechnologyConstants.MIN_TECHNOLOGIES + 1); - }); - - describe("owner", () => { - const FieldValidatorTester = BodyValidatorTester("owner"); - FieldValidatorTester.isRequired(); - }); - - describe("location", () => { - const FieldValidatorTester = BodyValidatorTester("location"); - FieldValidatorTester.isRequired(); - FieldValidatorTester.mustBeString(); - }); - - describe("requirements", () => { - const FieldValidatorTester = BodyValidatorTester("requirements"); - FieldValidatorTester.isRequired(); - }); - - describe("isHidden", () => { - const FieldValidatorTester = BodyValidatorTester("isHidden"); - FieldValidatorTester.mustBeBoolean(); - }); - }); - - describe("Without pre-existing offers", () => { - beforeAll(async () => { - await Offer.deleteMany({}); - }); - - beforeEach(async () => { - await Offer.deleteMany({}); - }); - - test("Should fail to create an offer due to publish end date being after publish date more than the limit", async () => { - const offer = generateTestOffer(); - const publishDate = new Date(Date.now()); - const offer_params = { - ...offer, - owner: test_company._id, - ownerName: test_company.name, - ownerLogo: test_company.logo, - publishDate: publishDate.toISOString(), - publishEndDate: (new Date(publishDate.getTime() + (MONTH_IN_MS * OFFER_MAX_LIFETIME_MONTHS) + DAY_TO_MS)).toISOString(), - }; - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)); - - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body.errors).toHaveLength(1); - expect(res.body.errors[0]).toHaveProperty("param", "publishEndDate"); - expect(res.body.errors[0]).toHaveProperty("location", "body"); - expect(res.body.errors[0].msg).toEqual( - ValidationReasons.MUST_BE_BEFORE( - new Date(publishDate.getTime() + (MONTH_IN_MS * OFFER_MAX_LIFETIME_MONTHS)).toISOString() - )); - }); - - // TODO: This test should be 'with minimum requirements' - // Thus, there should be another with all of the optional fields being sent, at least - test("Should successfully create an Offer", async () => { - const offer = generateTestOffer(); - const offer_params = { - ...offer, - owner: test_company._id, - }; - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)); - - expect(res.status).toBe(HTTPStatus.OK); - const created_offer_id = res.body._id; - - const created_offer = await Offer.findById(created_offer_id); - - expect(created_offer).toBeDefined(); - // Ideally matchers alongside .toMatchObject should be used in order to check created_offer against offer - // However, no matter what I tried, I couldn't get it to work :upside_down_face: - expect(created_offer).toHaveProperty("title", offer.title); - expect(created_offer).toHaveProperty("description", offer.description); - expect(created_offer).toHaveProperty("location", offer.location); - expect(created_offer).toHaveProperty("ownerName", test_company.name); - expect(created_offer).toHaveProperty("ownerLogo", test_company.logo); - }); - - test("Offer should be pending if the company hasn't been approved", async () => { - const offer = generateTestOffer({ owner: test_company._id }); - const res = await request() - .post("/offers/new") - .send(withGodToken(offer)).expect(HTTPStatus.OK); - expect(res.body.isPending).toBe(true); - }); - - test("Offer should not be pending if the company has been approved", async () => { - const offer = generateTestOffer({ owner: approved_test_company._id }); - const res = await request() - .post("/offers/new") - .send(withGodToken(offer)).expect(HTTPStatus.OK); - expect(res.body.isPending).toBe(false); - }); - - test("Should succeed to create an offer if the description's length is only shorter than the max \ - without HTML tags", async () => { - - const offer_params = { - ...generateTestOffer(), - description: `

${"a".repeat(OfferConstants.description.max_length)}

`, - owner: test_company._id, - }; - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)); - - expect(res.status).toBe(HTTPStatus.OK); - - const created_offer_id = res.body._id; - const created_offer = await Offer.findById(created_offer_id); - - expect(created_offer).toBeDefined(); - expect(created_offer).toHaveProperty("description", offer_params.description); - }); - - test("Should fail to create an offer if the description's length is longer than the max\ - without HTML tags", async () => { - - const offer_params = { - ...generateTestOffer(), - description: `

${"a".repeat(OfferConstants.description.max_length + 1)}

`, - owner: test_company._id, - }; - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body.errors).toHaveLength(1); - expect(res.body.errors[0]).toHaveProperty("param", "description"); - expect(res.body.errors[0]).toHaveProperty("location", "body"); - expect(res.body.errors[0].msg).toEqual(ValidationReasons.TOO_LONG(OfferConstants.description.max_length)); - }); - - test("Should fail to create an offer if jobStartDate is specified as null", async () => { - const offer_params = generateTestOffer({ - jobStartDate: null, - owner: test_company._id - }); - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body.errors).toHaveLength(1); - expect(res.body.errors[0]).toHaveProperty("param", "jobStartDate"); - expect(res.body.errors[0]).toHaveProperty("location", "body"); - expect(res.body.errors[0].msg).toEqual(ValidationReasons.DATE); - }); - - - }); - - describe("Before reaching the offers limit while having past offers", () => { - const testOffers = Array(CompanyConstants.offers.max_concurrent - 1) - .fill(generateTestOffer({ - "publishDate": (new Date(Date.now())).toISOString(), - "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() - })); - - testOffers.push(generateTestOffer({ - "publishDate": (new Date(Date.now() - (3 * DAY_TO_MS))).toISOString(), - "publishEndDate": (new Date(Date.now() - (2 * DAY_TO_MS))).toISOString() - })); - - beforeAll(async () => { - await Offer.deleteMany({}); - - testOffers.forEach((offer) => { - offer.owner = test_company._id; - offer.ownerName = test_company.name; - offer.ownerLogo = test_company.logo; - }); - - await Offer.create(testOffers); - }); - - afterAll(async () => { - await Offer.deleteMany({}); - }); - - test("should be able to create a new offer (past offers do not restrain the company)", async () => { - const offer_params = { - ...generateTestOffer(), - owner: test_company._id, - }; - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body).toHaveProperty("title", offer_params.title); - expect(res.body).toHaveProperty("description", offer_params.description); - expect(res.body).toHaveProperty("location", offer_params.location); - expect(res.body).toHaveProperty("ownerName", test_company.name); - expect(res.body).toHaveProperty("ownerLogo", test_company.logo); - }); - }); - - describe("After reaching the offers limit", () => { - const testOffers = Array(CompanyConstants.offers.max_concurrent) - .fill(generateTestOffer({ - "publishDate": (new Date(Date.now())).toISOString(), - "publishEndDate": (new Date(Date.now() + (DAY_TO_MS))).toISOString() - })); - - beforeAll(async () => { - await Offer.deleteMany({}); - - testOffers.forEach((offer) => { - offer.owner = test_company._id; - offer.ownerName = test_company.name; - offer.ownerLogo = test_company.logo; - }); - - await Offer.create(testOffers); - }); - - afterAll(async () => { - await Offer.deleteMany({}); - }); - - - test("should fail to create a new offer", async () => { - const offer_params = { - ...generateTestOffer(), - owner: test_company._id, - }; - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)); - - expect(res.status).toBe(HTTPStatus.CONFLICT); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors).toContainEqual( - { msg: ValidationReasons.MAX_CONCURRENT_OFFERS_EXCEEDED(CompanyConstants.offers.max_concurrent) }); - }); - - test("should fail to create a new offer (with default publishDate)", async () => { - const offer_params = { - ...generateTestOffer(), - owner: test_company._id, - }; - delete offer_params.publishDate; - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)); - - expect(res.status).toBe(HTTPStatus.CONFLICT); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors).toContainEqual( - { msg: ValidationReasons.MAX_CONCURRENT_OFFERS_EXCEEDED(CompanyConstants.offers.max_concurrent) }); - }); - }); - - describe("Trying to schedule an offer in a time period which reached the offers limit", () => { - const testOffers = Array(CompanyConstants.offers.max_concurrent) - .fill(generateTestOffer({ - "publishDate": (new Date(Date.now() + (3 * DAY_TO_MS))).toISOString(), - "publishEndDate": (new Date(Date.now() + (6 * DAY_TO_MS))).toISOString() - })); - - beforeAll(async () => { - await Offer.deleteMany({}); - - testOffers.forEach((offer) => { - offer.owner = test_company._id; - offer.ownerName = test_company.name; - offer.ownerLogo = test_company.logo; - }); - - await Offer.create(testOffers); - }); - - afterAll(async () => { - await Offer.deleteMany({}); - }); - - test("should fail to schedule a new offer", async () => { - const offer_params = { - ...generateTestOffer({ - "publishDate": (new Date(Date.now() + (4 * DAY_TO_MS))).toISOString(), - "publishEndDate": (new Date(Date.now() + (5 * DAY_TO_MS))).toISOString() - }), - owner: test_company._id, - }; - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)); - - expect(res.status).toBe(HTTPStatus.CONFLICT); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors).toContainEqual( - { msg: ValidationReasons.MAX_CONCURRENT_OFFERS_EXCEEDED(CompanyConstants.offers.max_concurrent) }); - }); - }); - - describe("Creating an offer in a time period with more than `max_concurrent` overlapping offers, \ - without exceeding the limit at any point", () => { - const testOffers = Array(CompanyConstants.offers.max_concurrent - 2) - .fill(generateTestOffer({ - "publishDate": (new Date(Date.now() + (2 * DAY_TO_MS))).toISOString(), - "publishEndDate": (new Date(Date.now() + (10 * DAY_TO_MS))).toISOString() - })); - - testOffers.push(generateTestOffer({ - "publishDate": (new Date(Date.now())).toISOString(), - "publishEndDate": (new Date(Date.now() + (5 * DAY_TO_MS))).toISOString() - })); - - testOffers.push(generateTestOffer({ - "publishDate": (new Date(Date.now() + (8 * DAY_TO_MS))).toISOString(), - "publishEndDate": (new Date(Date.now() + (12 * DAY_TO_MS))).toISOString() - })); - - beforeAll(async () => { - await Offer.deleteMany({}); - - testOffers.forEach((offer) => { - offer.owner = test_company._id; - offer.ownerName = test_company.name; - offer.ownerLogo = test_company.logo; - }); - - await Offer.create(testOffers); - }); - - test("should succeed to create an offer (the offers limit is never reached at any moment)", async () => { - const offer_params = generateTestOffer({ - "publishDate": (new Date(Date.now() + (4 * DAY_TO_MS))).toISOString(), - "publishEndDate": (new Date(Date.now() + (9 * DAY_TO_MS))).toISOString(), - owner: test_company._id, - }); - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)); - - expect(res.status).toBe(HTTPStatus.OK); - expect(res.body.publishDate).toBe(offer_params.publishDate); - expect(res.body.publishEndDate).toBe(offer_params.publishEndDate); - }); - }); - - describe("Default values", () => { - test("publishDate defaults to the current time if not provided", async () => { - const offer = { - title: "Test Offer", - publishEndDate: (new Date(Date.now() + (DAY_TO_MS))).toISOString(), - description: "For Testing Purposes", - contacts: ["geral@niaefeup.pt", "229417766"], - jobType: "SUMMER INTERNSHIP", - jobMinDuration: 1, - jobMaxDuration: 6, - fields: ["DEVOPS", "BACKEND", "OTHER"], - technologies: ["React", "CSS"], - owner: test_company._id, - ownerName: test_company.name, - ownerLogo: test_company.logo, - location: "Testing Street, Test City, 123", - requirements: ["The candidate must be tested", "Fluent in testJS"], - }; - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer)); - - expect(res.status).toBe(HTTPStatus.OK); - const created_offer_id = res.body._id; - - const created_offer = await Offer.findById(created_offer_id); - - expect(created_offer).toBeDefined(); - expect(created_offer).toHaveProperty("title", offer.title); - expect(created_offer).toHaveProperty("description", offer.description); - expect(created_offer).toHaveProperty("location", offer.location); - expect(created_offer).toHaveProperty("publishDate"); - expect(created_offer).toHaveProperty("ownerName", test_company.name); - expect(created_offer).toHaveProperty("ownerLogo", test_company.logo); - }); - }); - - describe("Job Duration", () => { - test("should fail if jobMinDuration is greater than jobMaxDuration", async () => { - const offer_params = generateTestOffer({ - jobMinDuration: 10, - jobMaxDuration: 8, - owner: test_company._id, - }); - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("param", "jobMaxDuration"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.MUST_BE_GREATER_THAN_OR_EQUAL_TO("jobMinDuration")); - }); - - test("should succeed if jobMaxDuration is greater than jobMinDuration", async () => { - const offer_params = generateTestOffer({ - jobMinDuration: 8, - jobMaxDuration: 10, - owner: test_company._id, - }); - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)); - - expect(res.status).toBe(HTTPStatus.OK); - }); - }); - - describe("Same 'publishDate' and 'publishEndDate'", () => { - - const date = (new Date(Date.now() + (DAY_TO_MS))).toISOString(); - let offer; - - beforeAll(() => { - // await Offer.deleteMany({}); - - offer = generateTestOffer({ - publishDate: date, - publishEndDate: date, - owner: test_company._id, - ownerName: test_company.name, - ownerLogo: test_company.logo, - }); - }); - - afterAll(async () => { - await Offer.deleteOne(offer); - }); - - test("should fail if 'publishDate' and 'publishEndDate' have the same value", async () => { - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer)); - - expect(res.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); - expect(res.body).toHaveProperty("error_code", ErrorTypes.VALIDATION_ERROR); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.MUST_BE_AFTER("publishDate")); - expect(res.body.errors[0]).toHaveProperty("param", "publishEndDate"); - expect(res.body.errors[0]).toHaveProperty("location", "body"); - }); + describe("Without pre-existing offers", () => { + beforeAll(async () => { + await Offer.deleteMany({}); }); - describe("Incomplete registration of the offer's company", () => { - let incomplete_test_company; - beforeAll(async () => { - incomplete_test_company = await Company.create({ - name: "incomplete test company", - bio: "a bio", - contacts: ["a contact"], - hasFinishedRegistration: false, - logo: "http://awebsite.com/alogo.jpg", - }); - }); - - afterAll(async () => { - await Company.deleteOne({ _id: incomplete_test_company._id }); - }); - - test("should fail to create offer if the company is not fully registered", async () => { - const offer_params = { - ...generateTestOffer(), - owner: incomplete_test_company._id, - ownerName: incomplete_test_company.name, - ownerLogo: incomplete_test_company.logo, - }; - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)); - - expect(res.status).toBe(HTTPStatus.FORBIDDEN); - expect(res.body).toHaveProperty("error_code", ErrorTypes.FORBIDDEN); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors).toContainEqual( - { msg: ValidationReasons.REGISTRATION_NOT_FINISHED }); - }); + beforeEach(async () => { + await Offer.deleteMany({}); }); - describe("Blocked company", () => { - - let blocked_test_company; - beforeAll(async () => { - blocked_test_company = await Company.create({ - name: "blocked test company", - bio: "a bio", - contacts: ["a contact"], - isBlocked: true, - hasFinishedRegistration: true - }); - }); - - test("should fail to create offer if company blocked", async () => { - const res = await request() - .post("/offers/new") - .send(withGodToken(generateTestOffer({ - owner: blocked_test_company._id, - ownerName: blocked_test_company.name, - }))); - - expect(res.status).toBe(HTTPStatus.FORBIDDEN); - expect(res.body).toHaveProperty("error_code", ErrorTypes.FORBIDDEN); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.COMPANY_BLOCKED); - }); - + test("Offer should be pending if the company hasn't been approved", async () => { + const offer = generateTestOffer({ owner: test_company._id }); + const res = await request() + .post("/offers/new") + .send(withGodToken(offer)).expect(HTTPStatus.OK); + expect(res.body.isPending).toBe(true); }); - describe("Disabled company", () => { - - let disabled_company; - - const disabled_company_user = { - email: "disabled_company@email.com", - password: "password123", - }; - - beforeAll(async () => { - // await Company.deleteMany({}); - // await Offer.deleteMany({}); - - disabled_company = await Company.create({ - name: "test company", - bio: "a bio", - contacts: ["a contact"], - hasFinishedRegistration: true, - logo: "http://awebsite.com/alogo.jpg", - isDisabled: true, - }); - - await Account.create({ - email: disabled_company_user.email, - password: await hash(disabled_company_user.password), - company: disabled_company._id - }); - }); - - test("Should not create offer if company is disabled, logged in as same company", async () => { - await test_agent - .post("/auth/login") - .send(disabled_company_user) - .expect(HTTPStatus.OK); - - const res = await test_agent - .post("/offers/new") - .send(generateTestOffer()); - - expect(res.status).toBe(HTTPStatus.FORBIDDEN); - expect(res.body).toHaveProperty("error_code", ErrorTypes.FORBIDDEN); - expect(res.body).toHaveProperty("errors"); - expect(res.body.errors).toContainEqual({ msg: ValidationReasons.COMPANY_DISABLED }); - }); + test("Offer should not be pending if the company has been approved", async () => { + const offer = generateTestOffer({ owner: approved_test_company._id }); + const res = await request() + .post("/offers/new") + .send(withGodToken(offer)).expect(HTTPStatus.OK); + expect(res.body.isPending).toBe(false); }); - - describe("applyURL validation", () => { - beforeAll(async () => { - await Offer.deleteMany({}); - }); - - beforeEach(async () => { - await Offer.deleteMany({}); - }); - - test("should fail if applyURL is neither a URL or an email", async () => { - const offer_params = generateTestOffer({ - applyURL: "this_is_not_valid", - owner: test_company._id, - }); - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)) - .expect(HTTPStatus.UNPROCESSABLE_ENTITY); - - expect(res.body.errors[0]).toHaveProperty("param", "applyURL"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.BAD_APPLY_URL); - }); - - test("should fail if applyURL is a URL with an unsupported protocol", async () => { - const offer_params = generateTestOffer({ - applyURL: "ftp://www.coolwebsite.com", - owner: test_company._id, - }); - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)) - .expect(HTTPStatus.UNPROCESSABLE_ENTITY); - - expect(res.body.errors[0]).toHaveProperty("param", "applyURL"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.BAD_APPLY_URL); - }); - - test("should fail if applyURL contains javascript code", async () => { - const offer_params = generateTestOffer({ - applyURL: "javascript:alert('hello friend');", - owner: test_company._id, - }); - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)) - .expect(HTTPStatus.UNPROCESSABLE_ENTITY); - - expect(res.body.errors[0]).toHaveProperty("param", "applyURL"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.BAD_APPLY_URL); - }); - - test("should fail if applyURL contains javascript code with a commented valid URL", async () => { - const offer_params = generateTestOffer({ - applyURL: "javascript:alert('hello friend'); // https://www.google.com", - owner: test_company._id, - }); - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)) - .expect(HTTPStatus.UNPROCESSABLE_ENTITY); - - expect(res.body.errors[0]).toHaveProperty("param", "applyURL"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.BAD_APPLY_URL); - }); - - test("should succeed if applyURL is a valid email", async () => { - const applyURL = "mailto:nicemail@gmail.com"; - const offer_params = generateTestOffer({ - applyURL, - owner: test_company._id, - }); - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)) - .expect(HTTPStatus.OK); - - expect(res.body).toHaveProperty("applyURL", applyURL); - }); - - test("should succeed if applyURL is a valid HTTP URL", async () => { - const applyURL = "http://www.coolwebsite.com/a/"; - const offer_params = generateTestOffer({ - applyURL, - owner: test_company._id, - }); - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)) - .expect(HTTPStatus.OK); - - expect(res.body).toHaveProperty("applyURL", applyURL); - }); - - test("should succeed if applyURL is a valid HTTPS URL", async () => { - const applyURL = "https://www.coolwebsite.com"; - const offer_params = generateTestOffer({ - applyURL, - owner: test_company._id, - }); - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)) - .expect(HTTPStatus.OK); - - expect(res.body).toHaveProperty("applyURL", applyURL); - }); - - test("should fail if applyURL is an invalid HTTPS URL", async () => { - const applyURL = "https://invalid"; - const offer_params = generateTestOffer({ - applyURL, - owner: test_company._id, - }); - - const res = await request() - .post("/offers/new") - .send(withGodToken(offer_params)) - .expect(HTTPStatus.UNPROCESSABLE_ENTITY); - - expect(res.body.errors[0]).toHaveProperty("param", "applyURL"); - expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.BAD_APPLY_URL); - }); - }); - }); + }); diff --git a/test/end-to-end/review.js b/test/end-to-end/review.js index aab25cdc..b5917da8 100644 --- a/test/end-to-end/review.js +++ b/test/end-to-end/review.js @@ -1,14 +1,16 @@ + + jest.mock("../../src/lib/emailService"); import EmailService, { EmailService as EmailServiceClass } from "../../src/lib/emailService"; jest.spyOn(EmailServiceClass.prototype, "verifyConnection").mockImplementation(() => Promise.resolve()); import { StatusCodes as HTTPStatus } from "http-status-codes"; -import CompanyApplication, { CompanyApplicationRules } from "../../src/models/CompanyApplication"; +import CompanyApplication from "../../src/models/CompanyApplication"; import hash from "../../src/lib/passwordHashing"; import Account from "../../src/models/Account"; -import { ErrorTypes } from "../../src/api/middleware/errorHandler"; import ApplicationStatus from "../../src/models/constants/ApplicationStatus"; import { APPROVAL_NOTIFICATION, REJECTION_NOTIFICATION } from "../../src/email-templates/companyApplicationApproval"; import mongoose from "mongoose"; +import AccountService from "../../src/services/account.js"; const { ObjectId } = mongoose.Types; @@ -141,7 +143,7 @@ describe("Company application review endpoint test", () => { expect(wrongFormatQuery.status).toBe(HTTPStatus.UNPROCESSABLE_ENTITY); expect(wrongFormatQuery.body.errors[0]).toStrictEqual({ location: "query", - msg: "must-be-in:[PENDING,APPROVED,REJECTED]", + msg: "must-be-in:[UNVERIFIED,PENDING,APPROVED,REJECTED]", param: "state", value: [`<["${ApplicationStatus.APPROVED}"]`] }); @@ -291,6 +293,12 @@ describe("Company application review endpoint test", () => { beforeEach(async () => { await Account.deleteMany({ email: pendingApplication.email }); application = await CompanyApplication.create(pendingApplication); + await (new AccountService()).registerCompany( + pendingApplication.email, + pendingApplication.password, + pendingApplication.companyName + ); + }); afterEach(async () => { @@ -298,13 +306,14 @@ describe("Company application review endpoint test", () => { }); test("Should approve pending application", async () => { - const res = await test_agent .post(`/applications/company/${application._id}/approve`); expect(res.status).toBe(HTTPStatus.OK); expect(res.body.email).toBe(pendingApplication.email); - expect(res.body.companyName).toBe(pendingApplication.companyName); + const approved_application = await CompanyApplication.findById(application._id); + expect(approved_application.state).toBe(ApplicationStatus.APPROVED); + }); test("Should send approval email to company email", async () => { @@ -348,26 +357,12 @@ describe("Company application review endpoint test", () => { .post(`/applications/company/${application._id}/reject`) .send({ rejectReason: "Some reason which is valid" }); - const res = await test_agent .post(`/applications/company/${application._id}/approve`); expect(res.status).toBe(HTTPStatus.CONFLICT); }); - test("Should fail if approving application with an existing account with same email, and then rollback", async () => { - await Account.create({ email: application.email, password: "passwordHashedButNotReally", isAdmin: true }); - - const res = await test_agent - .post(`/applications/company/${application._id}/approve`); - - expect(res.status).toBe(HTTPStatus.CONFLICT); - expect(res.body.error_code).toBe(ErrorTypes.VALIDATION_ERROR); - expect(res.body.errors[0].msg).toBe(CompanyApplicationRules.EMAIL_ALREADY_IN_USE.msg); - - const result_application = await CompanyApplication.findById(application._id); - expect(result_application.state).toBe(ApplicationStatus.PENDING); - }); }); describe("Reject application", () => { diff --git a/test/unit/token.js b/test/unit/token.js index d52461d4..dfa8d422 100644 --- a/test/unit/token.js +++ b/test/unit/token.js @@ -1,5 +1,7 @@ import { verifyAndDecodeToken, generateToken } from "../../src/lib/token"; import { SECOND_IN_MS } from "../../src/models/constants/TimeConstants"; +import { JsonWebTokenError } from "jsonwebtoken"; + describe("JWT Token tests", () => { const data = { @@ -20,7 +22,9 @@ describe("JWT Token tests", () => { }); test("should fail to decode token if invalid secret", () => { - expect(verifyAndDecodeToken(token, `${secret}o`)).toBeNull(); + expect(() => verifyAndDecodeToken(token, `${secret}o`)).toThrow(JsonWebTokenError); + expect(() => verifyAndDecodeToken(token, `${secret}o`)).toThrow("invalid signature"); + }); test("should fail to decode token if expired", () => { @@ -28,7 +32,8 @@ describe("JWT Token tests", () => { const mockDate = Date.now() + (11 * SECOND_IN_MS); Date.now = () => mockDate; - expect(verifyAndDecodeToken(token, `${secret}`)).toBeNull(); + expect(() => verifyAndDecodeToken(token, `${secret}`)).toThrow(JsonWebTokenError); + expect(() => verifyAndDecodeToken(token, `${secret}`)).toThrow("jwt expired"); Date.now = realTime; }); From e113bc83d00d7af6c5137b38b46aaa999c6f8303 Mon Sep 17 00:00:00 2001 From: FranciscoCardoso913 Date: Thu, 3 Aug 2023 16:17:28 +0100 Subject: [PATCH 23/30] Added tests for the endpoints applications/company/:id/approve and applications/company/:id/reject --- src/api/routes/review.js | 10 +- src/lib/emailService.js | 16 +- src/models/CompanyApplication.js | 14 +- src/services/application.js | 11 +- .../applications/company/:id/approve.js | 209 ++++++++++++++++++ .../applications/company/:id/reject.js | 204 +++++++++++++++++ 6 files changed, 449 insertions(+), 15 deletions(-) create mode 100644 test/end-to-end/applications/company/:id/approve.js create mode 100644 test/end-to-end/applications/company/:id/reject.js diff --git a/src/api/routes/review.js b/src/api/routes/review.js index 2baa0b1e..99d87c9e 100644 --- a/src/api/routes/review.js +++ b/src/api/routes/review.js @@ -6,7 +6,7 @@ import * as companyApplicationValidators from "../middleware/validators/applicat import ApplicationService, { CompanyApplicationAlreadyReviewed, CompanyApplicationEmailAlreadyInUse, - CompanyApplicationNotFound + CompanyApplicationNotFound, CompanyApplicationUnverified } from "../../services/application.js"; import { buildErrorResponse, ErrorTypes } from "../middleware/errorHandler.js"; @@ -96,7 +96,8 @@ export default (app) => { .json(buildErrorResponse(ErrorTypes.VALIDATION_ERROR, [{ msg: err.message }])); } else if ( err instanceof CompanyApplicationAlreadyReviewed || - err instanceof CompanyApplicationEmailAlreadyInUse + err instanceof CompanyApplicationEmailAlreadyInUse || + err instanceof CompanyApplicationUnverified ) { return res .status(HTTPStatus.CONFLICT) @@ -125,7 +126,10 @@ export default (app) => { return res .status(HTTPStatus.NOT_FOUND) .json(buildErrorResponse(ErrorTypes.VALIDATION_ERROR, [{ msg: err.message }])); - } else if (err instanceof CompanyApplicationAlreadyReviewed) { + } else if ( + err instanceof CompanyApplicationAlreadyReviewed || + err instanceof CompanyApplicationUnverified + ) { return res .status(HTTPStatus.CONFLICT) .json(buildErrorResponse(ErrorTypes.VALIDATION_ERROR, [{ msg: err.message }])); diff --git a/src/lib/emailService.js b/src/lib/emailService.js index d046f7ea..682c7f42 100644 --- a/src/lib/emailService.js +++ b/src/lib/emailService.js @@ -6,14 +6,16 @@ export class EmailService { async init({ email: user, password: pass }) { this.email = user; - const transporter = nodemailer.createTransport({ - host: 'smtp.ethereal.email', - port: 587, - secure: false, // true for 465, false for other ports + const transporter = await nodemailer.createTransport({ + pool: true, + host: "smtp.gmail.com", + port: 465, + secure: true, auth: { - user: "magdalen.labadie@ethereal.email", // generated ethereal user - pass: "GjdJdafFyj5svQBzJJ"// generated ethereal password - } + user, + pass + }, + connectionTimeout: 30000 }); transporter.use("compile", hbs({ diff --git a/src/models/CompanyApplication.js b/src/models/CompanyApplication.js index e3887313..b988b4d6 100644 --- a/src/models/CompanyApplication.js +++ b/src/models/CompanyApplication.js @@ -2,6 +2,7 @@ import mongoose from "mongoose"; import ApplicationStatus from "./constants/ApplicationStatus.js"; import CompanyApplicationConstants from "./constants/CompanyApplication.js"; import { checkDuplicatedEmail } from "../api/middleware/validators/validatorUtils.js"; +import { CompanyApplicationAlreadyReviewed, CompanyApplicationUnverified } from "../services/application.js"; const { Schema } = mongoose; @@ -39,6 +40,9 @@ export const CompanyApplicationRules = Object.freeze({ }, APPLICATION_ALREADY_VALIDATED: { msg: "application-already-validated", + }, + MUST_BE_VERIFIED: { + msg: "application-must-be-verified", } }); @@ -148,16 +152,22 @@ async function validateSingleActiveApplication(value) { export const isApprovable = (application) => { + if (application.state === ApplicationStatus.UNVERIFIED) + throw new CompanyApplicationUnverified(CompanyApplicationRules.MUST_BE_VERIFIED.msg); + if (application.state !== ApplicationStatus.PENDING) - throw new Error(CompanyApplicationRules.CANNOT_REVIEW_TWICE.msg); + throw new CompanyApplicationAlreadyReviewed(CompanyApplicationRules.CANNOT_REVIEW_TWICE.msg); return true; }; export const isRejectable = (application) => { + if (application.state === ApplicationStatus.UNVERIFIED) + throw new CompanyApplicationUnverified(CompanyApplicationRules.MUST_BE_VERIFIED.msg); + if (application.state !== ApplicationStatus.PENDING) - throw new Error(CompanyApplicationRules.CANNOT_REVIEW_TWICE.msg); + throw new CompanyApplicationAlreadyReviewed(CompanyApplicationRules.CANNOT_REVIEW_TWICE.msg); return true; }; diff --git a/src/services/application.js b/src/services/application.js index 28653fa2..bfb47d0e 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -38,6 +38,11 @@ export class CompanyApplicationAlreadyValidated extends Error { super(msg); } } +export class CompanyApplicationUnverified extends Error { + constructor(msg) { + super(msg); + } +} class CompanyApplicationService { @@ -184,8 +189,8 @@ class CompanyApplicationService { ...APPROVAL_NOTIFICATION(application.companyName), }); } catch (err) { - console.error("Error while approving company ", err); - throw new CompanyApplicationAlreadyReviewed(CompanyApplicationRules.CANNOT_REVIEW_TWICE.msg); + console.error("Error while approving company ", err.msg); + throw err; } return Account.findOne({ email: application.email }); } @@ -204,7 +209,7 @@ class CompanyApplicationService { return application.toObject(); } catch (e) { console.error(e); - throw new CompanyApplicationAlreadyReviewed(CompanyApplicationRules.CANNOT_REVIEW_TWICE.msg); + throw e; } } diff --git a/test/end-to-end/applications/company/:id/approve.js b/test/end-to-end/applications/company/:id/approve.js new file mode 100644 index 00000000..b5d78f4f --- /dev/null +++ b/test/end-to-end/applications/company/:id/approve.js @@ -0,0 +1,209 @@ +import AccountService from "../../../../../src/services/account.js"; +jest.mock("../../../../../src/lib/emailService"); +import { StatusCodes } from "http-status-codes"; +import { APPROVAL_NOTIFICATION } from "../../../../../src/email-templates/companyApplicationApproval"; +import EmailService, { EmailService as EmailServiceClass } from "../../../../../src/lib/emailService"; +import hash from "../../../../../src/lib/passwordHashing"; +import Account from "../../../../../src/models/Account"; +import CompanyApplication, { CompanyApplicationRules } from "../../../../../src/models/CompanyApplication"; +import ApplicationStatus from "../../../../../src/models/constants/ApplicationStatus"; +jest.spyOn(EmailServiceClass.prototype, "verifyConnection").mockImplementation(() => Promise.resolve()); + +import mongoose from "mongoose"; + +const { ObjectId } = mongoose.Types; + +describe("POST /applications/company/:id/approve", () => { + + const test_agent = agent(); + + const test_user_admin = { + email: "admin@email.com", + password: "password123", + }; + + beforeAll(async () => { + await CompanyApplication.deleteMany({}); + + await Account.deleteMany({}); + await Account.create({ + email: test_user_admin.email, + password: await hash(test_user_admin.password), + isAdmin: true + }); + }); + + afterAll(async () => { + await Account.deleteMany({}); + await CompanyApplication.deleteMany({}); + }); + + beforeEach(async () => { + // default login + await test_agent + .post("/auth/login") + .send(test_user_admin) + .expect(StatusCodes.OK); + }); + + describe("ID Validation", () => { + test("Should fail if trying to approve inexistent application", async () => { + + const id = new ObjectId(); + + await test_agent + .post(`/applications/company/${id}/approve`) + .expect(StatusCodes.NOT_FOUND); + + }); + }); + + describe("Without previous applications", () => { + + const pendingApplication1Data = { + email: "pending1@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", + submittedAt: new Date("2019-11-25"), + }; + const pendingApplication2Data = { + email: "pending2@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", + submittedAt: new Date("2019-11-25"), + }; + const unverifiedApplicationData = { + email: "unverified@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", + submittedAt: new Date("2019-11-25"), + isVerified: false + }; + + let pendingApplication1, pendingApplication2, unverifiedApplication; + + beforeAll(async () => { + await CompanyApplication.deleteMany({}); + + [ + pendingApplication1, + pendingApplication2, + unverifiedApplication + + ] = await CompanyApplication.create([ + pendingApplication1Data, + pendingApplication2Data, + unverifiedApplicationData + ]); + + await (new AccountService()).registerCompany( + pendingApplication1Data.email, + pendingApplication1Data.password, + pendingApplication1Data.companyName + ); + + await (new AccountService()).registerCompany( + pendingApplication2Data.email, + pendingApplication2Data.password, + pendingApplication2Data.companyName + ); + }); + + afterAll(async () => { + await CompanyApplication.deleteMany({}); + }); + + test("Should approve pending application", async () => { + + const res = await test_agent + .post(`/applications/company/${pendingApplication1._id}/approve`) + .expect(StatusCodes.OK); + + expect(res.body).toHaveProperty("email", pendingApplication1Data.email); + const approved_application = await CompanyApplication.findById(pendingApplication1._id); + expect(approved_application.state).toBe(ApplicationStatus.APPROVED); + }); + + test("Should send approval email to company email", async () => { + + await test_agent + .post(`/applications/company/${pendingApplication2._id}/approve`) + .expect(StatusCodes.OK); + + const emailOptions = APPROVAL_NOTIFICATION(pendingApplication2.companyName); + + expect(EmailService.sendMail).toHaveBeenCalledWith({ + subject: emailOptions.subject, + to: pendingApplication2.email, + template: emailOptions.template, + context: emailOptions.context, + }); + }); + + test("Should fail to approve unverified application", async () => { + + const res = await test_agent + .post(`/applications/company/${unverifiedApplication._id}/approve`) + .expect(StatusCodes.CONFLICT); + + expect(res.body.errors).toContainEqual(CompanyApplicationRules.MUST_BE_VERIFIED); + const approved_application = await CompanyApplication.findById(unverifiedApplication._id); + expect(approved_application.state).toBe(ApplicationStatus.UNVERIFIED); + }); + }); + + describe("With previous applications", () => { + + const approvedApplicationData = { + email: "approved@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", + submittedAt: new Date("2019-11-25"), + approvedAt: new Date("2019-11-26"), + rejectReason: null + }; + const rejectedApplicationData = { + email: "rejected@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", + submittedAt: new Date("2019-11-25"), + rejectedAt: new Date("2019-11-26"), + rejectReason: "test-reason" + }; + + let approvedApplication, rejectedApplication; + + beforeAll(async () => { + await CompanyApplication.deleteMany({}); + + [ + approvedApplication, + rejectedApplication, + ] = await CompanyApplication.create([ + approvedApplicationData, + rejectedApplicationData, + ]); + }); + + afterAll(async () => { + await CompanyApplication.deleteMany({}); + }); + + test("Should fail if trying to approve already approved application", async () => { + await test_agent + .post(`/applications/company/${approvedApplication._id}/approve`) + .expect(StatusCodes.CONFLICT); + }); + + test("Should fail if trying to approve already rejected application", async () => { + await test_agent + .post(`/applications/company/${rejectedApplication._id}/approve`) + .expect(StatusCodes.CONFLICT); + }); + }); +}); diff --git a/test/end-to-end/applications/company/:id/reject.js b/test/end-to-end/applications/company/:id/reject.js new file mode 100644 index 00000000..1bad155d --- /dev/null +++ b/test/end-to-end/applications/company/:id/reject.js @@ -0,0 +1,204 @@ +jest.mock("../../../../../src/lib/emailService"); +import EmailService, { EmailService as EmailServiceClass } from "../../../../../src/lib/emailService"; +jest.spyOn(EmailServiceClass.prototype, "verifyConnection").mockImplementation(() => Promise.resolve()); +import { StatusCodes } from "http-status-codes"; +import Account from "../../../../../src/models/Account"; +import CompanyApplication, { CompanyApplicationRules } from "../../../../../src/models/CompanyApplication"; +import hash from "../../../../../src/lib/passwordHashing"; +import { REJECTION_NOTIFICATION } from "../../../../../src/email-templates/companyApplicationApproval"; + +import mongoose from "mongoose"; + +const { ObjectId } = mongoose.Types; + +describe("POST /applications/company/:id/reject", () => { + + const test_agent = agent(); + + const test_user_admin = { + email: "admin@email.com", + password: "password123", + }; + + beforeAll(async () => { + await CompanyApplication.deleteMany({}); + + await Account.deleteMany({}); + await Account.create({ + email: test_user_admin.email, + password: await hash(test_user_admin.password), + isAdmin: true + }); + }); + + afterAll(async () => { + await Account.deleteMany({}); + await CompanyApplication.deleteMany({}); + }); + + beforeEach(async () => { + // default login + await test_agent + .post("/auth/login") + .send(test_user_admin) + .expect(StatusCodes.OK); + }); + + describe("ID Validation", () => { + test("Should fail if trying to reject non existent application", async () => { + + const id = new ObjectId(); + + await test_agent + .post(`/applications/company/${id}/reject`) + .send({ rejectReason: "Some reason which is valid" }) + .expect(StatusCodes.NOT_FOUND); + }); + }); + + describe("Without previous applications", () => { + + const pendingApplication1Data = { + email: "pending1@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", + submittedAt: new Date("2019-11-25"), + }; + const pendingApplication2Data = { + email: "pending2@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", + submittedAt: new Date("2019-11-25"), + }; + + const unverifiedApplicationData = { + email: "unverified@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", + submittedAt: new Date("2019-11-25"), + isVerified: false + }; + + let pendingApplication1, pendingApplication2, unverifiedApplication; + + beforeAll(async () => { + await CompanyApplication.deleteMany({}); + + [ + pendingApplication1, + pendingApplication2, + unverifiedApplication, + ] = await CompanyApplication.create([ + pendingApplication1Data, + pendingApplication2Data, + unverifiedApplicationData, + ]); + }); + + afterAll(async () => { + await CompanyApplication.deleteMany({}); + }); + + test("Should fail if no rejectReason provided", async () => { + const res = await test_agent + .post(`/applications/company/${pendingApplication1._id}/reject`); + + expect(res.status).toBe(StatusCodes.UNPROCESSABLE_ENTITY); + expect(res.body.errors[0]).toStrictEqual({ location: "body", msg: "required", param: "rejectReason" }); + }); + + test("Should fail if application is not verified", async () => { + const res = await test_agent + .post(`/applications/company/${unverifiedApplication._id}/reject`) + .send({ rejectReason: "Some reason which is valid" }) + .expect(StatusCodes.CONFLICT); + + expect(res.body.errors).toContainEqual(CompanyApplicationRules.MUST_BE_VERIFIED); + }); + + test("Should reject pending application", async () => { + + const res = await test_agent + .post(`/applications/company/${pendingApplication1._id}/reject`) + .send({ rejectReason: "Some reason which is valid" }) + .expect(StatusCodes.OK); + + expect(res.body).toHaveProperty("email", pendingApplication1Data.email); + expect(res.body).toHaveProperty("companyName", pendingApplication1Data.companyName); + }); + + test("Should send rejection email to company email", async () => { + + await test_agent + .post(`/applications/company/${pendingApplication2._id}/reject`) + .send({ rejectReason: "Some reason which is valid" }) + .expect(StatusCodes.OK); + + const emailOptions = REJECTION_NOTIFICATION(pendingApplication2.companyName); + + expect(EmailService.sendMail).toHaveBeenCalledWith({ + subject: emailOptions.subject, + to: pendingApplication2.email, + template: emailOptions.template, + context: emailOptions.context, + }); + }); + }); + + describe("With previous applications", () => { + + const approvedApplicationData = { + email: "approved@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", + submittedAt: new Date("2019-11-25"), + approvedAt: new Date("2019-11-26"), + rejectReason: null + }; + const rejectedApplicationData = { + email: "rejected@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", + submittedAt: new Date("2019-11-25"), + rejectedAt: new Date("2019-11-26"), + rejectReason: "test-reason" + }; + + let approvedApplication, rejectedApplication; + + beforeAll(async () => { + await CompanyApplication.deleteMany({}); + + [ + approvedApplication, + rejectedApplication, + ] = await CompanyApplication.create([ + approvedApplicationData, + rejectedApplicationData, + ]); + }); + + afterAll(async () => { + await CompanyApplication.deleteMany({}); + }); + + test("Should fail if trying to reject already approved application", async () => { + await test_agent + .post(`/applications/company/${approvedApplication._id}/reject`) + .send({ rejectReason: "Some reason which is valid" }) + .expect(StatusCodes.CONFLICT); + }); + + test("Should fail if trying to reject already rejected application", async () => { + await test_agent + .post(`/applications/company/${rejectedApplication._id}/reject`) + .send({ rejectReason: "Some reason which is valid" }) + .expect(StatusCodes.CONFLICT); + }); + }); +}); From 64b8c31a8a48039ac51f292780a725d9c99fe4ea Mon Sep 17 00:00:00 2001 From: FranciscoCardoso913 Date: Wed, 23 Aug 2023 18:26:55 +0100 Subject: [PATCH 24/30] Changed endpoint that returned company's state to return company's application Co-authored-by: Daniel Ferreira --- src/api/routes/company.js | 8 ++-- src/services/account.js | 2 +- .../:companyId/{state.js => application.js} | 41 ++++++++++++------- 3 files changed, 32 insertions(+), 19 deletions(-) rename test/end-to-end/company/:companyId/{state.js => application.js} (76%) diff --git a/src/api/routes/company.js b/src/api/routes/company.js index 6407cf58..65a614bc 100644 --- a/src/api/routes/company.js +++ b/src/api/routes/company.js @@ -258,9 +258,9 @@ export default (app) => { ); /** - * Get the state of a company with its id + * Get the application of a company with its id */ - router.get("/:companyId/state", + router.get("/:companyId/application", or([ authMiddleware.isAdmin, authMiddleware.isGod, @@ -272,8 +272,8 @@ export default (app) => { try { const account = await Account.findOne({ "company": req.params.companyId }); - const application = await CompanyApplication.findOne({ "email": account.email }); - return res.json(application.state); + const application = (await CompanyApplication.findOne({ "email": account.email })).toObject(); + return res.json(application); } catch (err) { console.error(err); return next(err); diff --git a/src/services/account.js b/src/services/account.js index caeaae1d..12831d3e 100644 --- a/src/services/account.js +++ b/src/services/account.js @@ -31,7 +31,7 @@ class AccountService { await Account.create({ email, - password: await hash(password), + password: (password), company, }); } diff --git a/test/end-to-end/company/:companyId/state.js b/test/end-to-end/company/:companyId/application.js similarity index 76% rename from test/end-to-end/company/:companyId/state.js rename to test/end-to-end/company/:companyId/application.js index 482f671d..23458d93 100644 --- a/test/end-to-end/company/:companyId/state.js +++ b/test/end-to-end/company/:companyId/application.js @@ -5,8 +5,10 @@ import Company from "../../../../src/models/Company.js"; import AccountService from "../../../../src/services/account.js"; import CompanyApplicationService from "../../../../src/services/application.js"; import withGodToken from "../../../utils/GodToken.js"; +import hash from "../../../../src/lib/passwordHashing.js"; -describe("GET /company/:companyId/state", () => { + +describe("GET /company/:companyId/application", () => { const test_agent = agent(); let companyId; @@ -42,14 +44,15 @@ describe("GET /company/:companyId/state", () => { motivation: "I want people for job :)" }); await accountService.registerAdmin(test_user_admin.email, test_user_admin.password); - await accountService.registerCompany(test_user_company1.email, test_user_company1.password, "test company"); - await accountService.registerCompany(test_user_company2.email, test_user_company2.password, "test company 2"); + await accountService.registerCompany(test_user_company1.email, await hash(test_user_company1.password), "test company"); + await accountService.registerCompany(test_user_company2.email, await hash(test_user_company2.password), "test company 2"); companyId = (await Company.findOne({ name: "test company" }))._id; }); afterEach(async () => { + await test_agent .delete("/auth/login"); }); @@ -67,7 +70,7 @@ describe("GET /company/:companyId/state", () => { .expect(StatusCodes.OK); const res = await test_agent - .get(`/company/${companyId.toString()}/state`); + .get(`/company/${companyId.toString()}/application`); expect(res.status).toBe(StatusCodes.OK); }); @@ -80,7 +83,7 @@ describe("GET /company/:companyId/state", () => { .expect(StatusCodes.OK); const res = await test_agent - .get(`/company/${companyId}/state`) + .get(`/company/${companyId}/application`) .send(withGodToken()); expect(res.status).toBe(StatusCodes.OK); @@ -93,14 +96,14 @@ describe("GET /company/:companyId/state", () => { .expect(StatusCodes.OK); const res = await test_agent - .get(`/company/${companyId}/state`); + .get(`/company/${companyId}/application`); expect(res.status).toBe(StatusCodes.OK); }); test("Should failed if the user is not logged in", async () => { await test_agent - .get(`/company/${companyId}/state`).expect(StatusCodes.UNAUTHORIZED); + .get(`/company/${companyId}/application`).expect(StatusCodes.UNAUTHORIZED); }); @@ -111,14 +114,15 @@ describe("GET /company/:companyId/state", () => { .expect(StatusCodes.OK); await test_agent - .get(`/company/${companyId}/state`) + .get(`/company/${companyId}/application`) .expect(StatusCodes.UNAUTHORIZED); }); }); describe("Testing endpoint's result", () => { let application; - + const RealDateNow = Date.now; + const mockCurrentDate = new Date("2019-11-23"); beforeAll(async () => { await Account.deleteMany({}); await Company.deleteMany({}); @@ -126,15 +130,19 @@ describe("GET /company/:companyId/state", () => { await test_agent .delete("/auth/login"); const accountService = new AccountService(); + + Date.now = () => mockCurrentDate.getTime(); + application = await (new CompanyApplicationService()).create({ email: test_user_company1.email, password: test_user_company1.password, companyName: "test company", - motivation: "I want people for job :)" + motivation: "I want people for job :)", }); - await accountService.registerCompany(test_user_company1.email, test_user_company1.password, "test company"); + await accountService.registerCompany(test_user_company1.email, await hash(test_user_company1.password), "test company"); companyId = (await Company.findOne({ name: "test company" }))._id; + Date.now = RealDateNow; }); afterAll(async () => { @@ -143,17 +151,22 @@ describe("GET /company/:companyId/state", () => { await CompanyApplication.deleteMany({}); }); - test("Should return the state of the application", async () => { + test("Should return the company's application", async () => { await test_agent .post("/auth/login") .send(test_user_company1) .expect(StatusCodes.OK); const res = await test_agent - .get(`/company/${companyId}/state`) + .get(`/company/${companyId}/application`) .expect(StatusCodes.OK); - expect(res.body).toBe(application.state); + expect(res.body).toBeDefined(); + expect(res.body).toHaveProperty("email", application.email); + expect(res.body).toHaveProperty("companyName", application.companyName); + expect(res.body).toHaveProperty("motivation", application.motivation); + expect(res.body).toHaveProperty("submittedAt", mockCurrentDate.toJSON()); + expect(res.body).not.toHaveProperty("password", application.password); }); }); From 96719ac785aefea400bbfff97c6f2a43a42e8b8c Mon Sep 17 00:00:00 2001 From: FranciscoCardoso913 Date: Fri, 25 Aug 2023 16:00:55 +0100 Subject: [PATCH 25/30] Clear unused functions and unneeded verifications and made more tests to previously uncover parts --- src/api/routes/review.js | 2 -- src/services/application.js | 23 +++---------- .../applications/company/:id/approve.js | 32 +++++++++++++++++-- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/api/routes/review.js b/src/api/routes/review.js index 99d87c9e..89965f98 100644 --- a/src/api/routes/review.js +++ b/src/api/routes/review.js @@ -5,7 +5,6 @@ import * as authMiddleware from "../middleware/auth.js"; import * as companyApplicationValidators from "../middleware/validators/application.js"; import ApplicationService, { CompanyApplicationAlreadyReviewed, - CompanyApplicationEmailAlreadyInUse, CompanyApplicationNotFound, CompanyApplicationUnverified } from "../../services/application.js"; @@ -96,7 +95,6 @@ export default (app) => { .json(buildErrorResponse(ErrorTypes.VALIDATION_ERROR, [{ msg: err.message }])); } else if ( err instanceof CompanyApplicationAlreadyReviewed || - err instanceof CompanyApplicationEmailAlreadyInUse || err instanceof CompanyApplicationUnverified ) { return res diff --git a/src/services/application.js b/src/services/application.js index bfb47d0e..a471dcb1 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -183,12 +183,14 @@ class CompanyApplicationService { const application = await CompanyApplication.findById(id, {}, options); if (!application) throw new CompanyApplicationNotFound(CompanyApplicationRules.MUST_EXIST_TO_APPROVE.msg); try { - application.approve(); + await application.approve(); await EmailService.sendMail({ to: application.email, ...APPROVAL_NOTIFICATION(application.companyName), }); } catch (err) { + if (!(err instanceof CompanyApplicationUnverified || err instanceof CompanyApplicationAlreadyReviewed)) + await application.undoApproval(); console.error("Error while approving company ", err.msg); throw err; } @@ -218,18 +220,6 @@ class CompanyApplicationService { return `${config.application_confirmation_link}${token}/validate`; } - async sendConfirmationNotification(email, link) { - try { - await EmailService.sendMail({ - to: email, - ...APPLICATION_CONFIRMATION(link), - }); - } catch (err) { - console.error(err); - throw err; - } - } - async applicationValidation(id) { const application = await this.findById(id); @@ -253,11 +243,8 @@ class CompanyApplicationService { await (new AccountService()).registerCompany(application.email, application.password, application.companyName); } catch (err) { console.error("Error creating account for validated Company Application", err); - if (err.name === "MongoServerError" && /E11000\s.*collection:\s.*\.accounts.*/.test(err.msg)) { - throw new CompanyApplicationEmailAlreadyInUse(CompanyApplicationRules.EMAIL_ALREADY_IN_USE.msg); - } else { - throw err; - } + throw err; + } } diff --git a/test/end-to-end/applications/company/:id/approve.js b/test/end-to-end/applications/company/:id/approve.js index b5d78f4f..a09822e8 100644 --- a/test/end-to-end/applications/company/:id/approve.js +++ b/test/end-to-end/applications/company/:id/approve.js @@ -10,6 +10,7 @@ import ApplicationStatus from "../../../../../src/models/constants/ApplicationSt jest.spyOn(EmailServiceClass.prototype, "verifyConnection").mockImplementation(() => Promise.resolve()); import mongoose from "mongoose"; +import ValidationReasons from "../../../../../src/api/middleware/validators/validationReasons.js"; const { ObjectId } = mongoose.Types; @@ -47,7 +48,7 @@ describe("POST /applications/company/:id/approve", () => { }); describe("ID Validation", () => { - test("Should fail if trying to approve inexistent application", async () => { + test("Should fail if trying to approve not existent application", async () => { const id = new ObjectId(); @@ -74,6 +75,13 @@ describe("POST /applications/company/:id/approve", () => { motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", submittedAt: new Date("2019-11-25"), }; + const pendingApplication3Data = { + email: "pending3@test.com", + password: "password123", + companyName: "Testing company", + motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", + submittedAt: new Date("2019-11-25"), + }; const unverifiedApplicationData = { email: "unverified@test.com", password: "password123", @@ -83,7 +91,7 @@ describe("POST /applications/company/:id/approve", () => { isVerified: false }; - let pendingApplication1, pendingApplication2, unverifiedApplication; + let pendingApplication1, pendingApplication2, pendingApplication3, unverifiedApplication; beforeAll(async () => { await CompanyApplication.deleteMany({}); @@ -91,11 +99,13 @@ describe("POST /applications/company/:id/approve", () => { [ pendingApplication1, pendingApplication2, + pendingApplication3, unverifiedApplication ] = await CompanyApplication.create([ pendingApplication1Data, pendingApplication2Data, + pendingApplication3Data, unverifiedApplicationData ]); @@ -110,6 +120,11 @@ describe("POST /applications/company/:id/approve", () => { pendingApplication2Data.password, pendingApplication2Data.companyName ); + await (new AccountService()).registerCompany( + pendingApplication3Data.email, + pendingApplication3Data.password, + pendingApplication3Data.companyName + ); }); afterAll(async () => { @@ -153,6 +168,19 @@ describe("POST /applications/company/:id/approve", () => { const approved_application = await CompanyApplication.findById(unverifiedApplication._id); expect(approved_application.state).toBe(ApplicationStatus.UNVERIFIED); }); + test("if email fails to be sent application should not be approved", async () => { + jest.spyOn(EmailServiceClass.prototype, "sendMail").mockImplementation(() => { + throw Error(); + }); + const res = await test_agent + .post(`/applications/company/${pendingApplication3._id}/approve`) + .expect(StatusCodes.INTERNAL_SERVER_ERROR); + + jest.spyOn(EmailServiceClass.prototype, "sendMail").mockClear(); + expect(res.body.errors).toContainEqual({ msg: ValidationReasons.UNKNOWN }); + const pending_application = await CompanyApplication.findById(pendingApplication3._id); + expect(pending_application.state).toBe(ApplicationStatus.PENDING); + }); }); describe("With previous applications", () => { From 43a1e443b1b516d8d68c4a936765f73f5681114a Mon Sep 17 00:00:00 2001 From: Francisco Cardoso Date: Tue, 29 Aug 2023 21:26:40 +0100 Subject: [PATCH 26/30] Updating the API documentation --- documentation/docs-index.js | 6 +- documentation/docs/applications/approve.md | 36 + documentation/docs/applications/create.md | 45 +- documentation/docs/applications/reject.md | 38 + documentation/docs/applications/search.md | 17 +- documentation/docs/applications/validate.md | 161 + documentation/docs/auth/confirm.md | 39 +- documentation/docs/auth/finish-recovery.md | 39 +- .../docs/companies/get-application.md | 190 + documentation/docs/offers/create.md | 1 + documentation/docs/offers/search.md | 2 + documentation/package-lock.json | 2818 +++++++- documentation/package.json | 2 +- package-lock.json | 6254 ++++++++--------- 14 files changed, 6073 insertions(+), 3575 deletions(-) create mode 100644 documentation/docs/applications/validate.md create mode 100644 documentation/docs/companies/get-application.md diff --git a/documentation/docs-index.js b/documentation/docs-index.js index cce0cb47..1134eed7 100644 --- a/documentation/docs-index.js +++ b/documentation/docs-index.js @@ -28,13 +28,15 @@ module.exports = { "companies/disable", "companies/enable", "companies/delete", - "companies/concurrent-offers" + "companies/concurrent-offers", + "companies/get-application" ], Applications: [ "applications/create", "applications/search", "applications/approve", - "applications/reject" + "applications/reject", + "applications/validate" ], Auth: [ "auth/login", diff --git a/documentation/docs/applications/approve.md b/documentation/docs/applications/approve.md index f771615d..4a530069 100644 --- a/documentation/docs/applications/approve.md +++ b/documentation/docs/applications/approve.md @@ -13,6 +13,7 @@ import Highlight from "../../src/highlight.js" ## Details This endpoint is used to approve a company Application, specified by applicationId. +It changes all the companies offers to not pending. **URL** : `/applications/company/:applicationId/approve` @@ -169,3 +170,38 @@ values={[ +### Example 5 - Application is not verified + +**Code** : 409 CONFLICT + + + + + +```bash +/applications/company/631a18cf8e61e0acea76e5e1/approve +``` + + + + + +```json +{ + "error_code": 1, + "errors": [ + { + "msg": "application-must-be-verified" + } + ] +} +``` + + + diff --git a/documentation/docs/applications/create.md b/documentation/docs/applications/create.md index 3524f1ae..cc0786e4 100644 --- a/documentation/docs/applications/create.md +++ b/documentation/docs/applications/create.md @@ -13,7 +13,7 @@ import Highlight from "../../src/highlight.js" ## Details This endpoint is used to create company applications. -In order of a Company to use its account, the application must be accepted by an Admin and then the Company should +In order of a Company to use its account, the company must verify its application by clicking in a link sent by email after the creation of the application and then the Company should finish its registration. **URL** : `/apply/company` @@ -249,7 +249,48 @@ values={[ -### Example 5 - Invalid Password +### Example 5 - Application with the same email created recently + +**Code** : 403 FORBIDDEN + + + + + +```json +{ + "email": "company@company.com", + "password": "password123", + "companyName": "Company", + "motivation": "We wish to revolutionize the industry with young engineers." +} +``` + + + + + +```json +{ + "error_code": 1, + "errors": [ + { + "msg": "company-application-recently-created", + } + ] +} +``` + + + + +### Example 6 - Invalid Password **Code** : 422 UNPROCESSABLE ENTITY diff --git a/documentation/docs/applications/reject.md b/documentation/docs/applications/reject.md index c9e3b9a7..2a889402 100644 --- a/documentation/docs/applications/reject.md +++ b/documentation/docs/applications/reject.md @@ -197,3 +197,41 @@ values={[ +### Example 5 - Application is not verified + +**Code** : 409 CONFLICT + + + + + +```json +{ + "rejectReason": "The motivation of the company is not convincing" +} +``` + + + + + +```json +{ + "error_code": 1, + "errors": [ + { + "msg": "application-must-be-verified" + } + ] +} +``` + + + + diff --git a/documentation/docs/applications/search.md b/documentation/docs/applications/search.md index dc8227d4..a96a6171 100644 --- a/documentation/docs/applications/search.md +++ b/documentation/docs/applications/search.md @@ -66,7 +66,7 @@ Filters the applications by the name of the respective companies. Array of strings which filters the application by their state. :::caution -Must be a valid state (currently `["PENDING", "APPROVED", "REJECTED"]`). +Must be a valid state (currently `["UNVERIFIED", "PENDING", "APPROVED", "REJECTED"]`). ::: ### submissionDateFrom @@ -153,6 +153,7 @@ values={[ "companyName": "Company name", "motivation": "We wish to revolutionize the industry with young engineers.", "submittedAt": "2022-09-08T16:31:11.784Z", + "isVerified": true, "__v": 0, "state": "PENDING" }, @@ -162,6 +163,7 @@ values={[ "companyName": "Example Company", "motivation": "We are a brand new tech company in Porto, Portugal", "submittedAt": "2022-09-07T13:15:15.971Z", + "isVerified": true, "__v": 0, "approvedAt": "2022-09-07T13:17:30.908Z", "state": "APPROVED" @@ -172,13 +174,24 @@ values={[ "companyName": "Bad Company", "motivation": "We want to exploit workers.", "submittedAt": "2022-09-07T13:15:15.971Z", + "isVerified": true, "__v": 0, "rejectedAt": "2022-09-07T13:17:30.908Z", "rejectReason": "Motivation doesn't seem right", "state": "REJECTED" + }, + { + "_id": "63189963541e53a45a423dce", + "email": "notVerified@company.com", + "companyName": "Unverified", + "motivation": "We are a new company in Lisbon", + "submittedAt": "2022-09-07T13:15:15.971Z", + "isVerified": false, + "__v": 0, + "state": "PENDING" } ], - "docCount": 3 + "docCount": 4 } ``` diff --git a/documentation/docs/applications/validate.md b/documentation/docs/applications/validate.md new file mode 100644 index 00000000..526798a2 --- /dev/null +++ b/documentation/docs/applications/validate.md @@ -0,0 +1,161 @@ +--- +id: validate +title: Validate Application +sidebar_label: Validate Application +slug: /applications/validate +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +import Highlight from "../../src/highlight.js" + +## Details + +This endpoint is used to validate an application using a previous created token. +The token is generated with the [ create ](./create) endpoint and is sent to the user by email. + + +**URL** : `/apply/company/:token/validate` + +**Method** : POST + +## Request examples + +### Example 1 - Valid Request + +**Code** : 200 OK + + + + + +```bash +/apply/company/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im5pQGFlZmV1cC5wdCIsImlhdCI6MTY2MzAxMzg0OSwiZXhwIjoxNjYzMDE0NDQ5fQ.k5Z_nBpqt_Hs8JBhLH0ZXTl2-BG-utdIAUdhKXEFuFc/validate +``` + + + + + +```json +{} +``` + + + + +### Example 2 - Invalid Token + +**Code** : 404 NOT_FOUND + + + + + +```bash +/apply/company/invalid/validate + +``` + + + + + +```json +{ + "error_code": 3, + "errors": [ + { + "msg": "invalid-token" + } + ] +} +``` + + + + +### Example 3 - Expired Token + +**Code** : 410 GONE + + + + + +```bash +/apply/company/expired/validate +``` + + + + + +```json +{ + "error_code": 3, + "errors": [ + { + "msg": "expired-token" + } + ] +} +``` + + + + +### Example 4 - Application Already Validated + +**Code** : 409 CONFLICT + + + + + +```bash +/apply/company/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im5pQGFlZmV1cC5wdCIsImlhdCI6MTY2MzAxMzg0OSwiZXhwIjoxNjYzMDE0NDQ5fQ.k5Z_nBpqt_Hs8JBhLH0ZXTl2-BG-utdIAUdhKXEFuFc/validate +``` + + + + + +```json +{ + "error_code": 3, + "errors": [ + { + "msg": "application-already-validated" + } + ] +} +``` + + + diff --git a/documentation/docs/auth/confirm.md b/documentation/docs/auth/confirm.md index b758f236..254c32a5 100644 --- a/documentation/docs/auth/confirm.md +++ b/documentation/docs/auth/confirm.md @@ -52,7 +52,7 @@ values={[ ### Example 2 - Invalid Token -**Code** : 403 FORBIDDEN +**Code** : 404 NOT_FOUND + +### Example 3 - Expired Token + +**Code** : 410 GONE + + + + + +```bash +/auth/recover/expired/confirm +``` + + + + + +```json +{ + "error_code": 3, + "errors": [ + { + "msg": "expired-token" + } + ] +} +``` + + + + diff --git a/documentation/docs/auth/finish-recovery.md b/documentation/docs/auth/finish-recovery.md index bf876184..f3286f39 100644 --- a/documentation/docs/auth/finish-recovery.md +++ b/documentation/docs/auth/finish-recovery.md @@ -66,7 +66,7 @@ values={[ ### Example 2 - Invalid Token -**Code** : 403 FORBIDDEN +**Code** : 404 NOT_FOUND -### Example 3 - Password Without Numbers + +**Code** : 410 GONE + + + + + +```bash +/auth/recover/expired/confirm +``` + + + + + +```json +{ + "error_code": 3, + "errors": [ + { + "msg": "expired-token" + } + ] +} +``` + + + + +### Example 4 - Password Without Numbers **Code** : 422 UNPROCESSABLE ENTITY diff --git a/documentation/docs/companies/get-application.md b/documentation/docs/companies/get-application.md new file mode 100644 index 00000000..c1dbccdf --- /dev/null +++ b/documentation/docs/companies/get-application.md @@ -0,0 +1,190 @@ +--- +id: get-application +title: Get Company Application by Company Id +sidebar_label: Get Application by Company Id +slug: /companies/get-application +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +import Highlight from "../../src/highlight.js" + +## Details + +This endpoint returns an application of a Company based on the Company ID provided. + +**URL** : `/company/:companyId/application` + +**Method** : GET + +:::caution Authentication +Auth is required to get the application. Only Admins or owners of the company will have permission. Otherwise, if in god mode, [god_token](#god_token) must be provided. +::: + +## Parameters + +### god_token + +Body Parameter + +Optional +String + +If set, will use this for validating the usage of god mode (in case no session details are available, i.e., no logged-in +user). + +## Request examples + +### Example 1 - Valid Request + +**Code** : 200 OK + + + + + +```bash +/company/649a1ac0282d8ea3c574e25f/application +``` + + + + + +```json +{ + "_id": "649a1ab4282d8ea3c574e259", + "email": "company@example.com", + "companyName": "Company", + "motivation": "We wish to revolutionize the industry with young engineers.", + "submittedAt": "2023-06-26T23:09:40.450Z", + "isVerified": true, + "__v": 0, + "approvedAt": "2023-06-26T23:11:37.488Z", + "state": "APPROVED" +} +``` + + + + +### Example 2 - Insufficient permission + +**Code** : 401 UNAUTHORIZED + + + + + +```bash +/company/649a1ac0282d8ea3c574e25f/application +``` + + + + + +```json +{ + "error_code": 3, + "errors": [ + { + "msg": "insufficient-permissions" + } + ] +} +``` + + + + +### Example 3 - Invalid ID + +**Code** : 422 UNPROCESSABLE ENTITY + + + + + +```bash +/company/invalid/application +``` + + + + + +```json +{ + "error_code": 1, + "errors": [ + { + "value": "invalid", + "msg": "must-be-a-valid-id", + "param": "companyId", + "location": "params" + } + ] +} +``` + + + + +### Example 4 - Non-Existing Company + +**Code** : 422 UNPROCESSABLE ENTITY + + + + + +```bash +/company/649a1ac0282d8ea3c574e26f/application +``` + + + + + +```json +{ + "error_code": 1, + "errors": [ + { + "value": "649a1ac0282d8ea3c574e26f", + "msg": "no-company-found-with-id:649a1ac0282d8ea3c574e26f", + "param": "companyId", + "location": "params" + } + ] +} +``` + + + diff --git a/documentation/docs/offers/create.md b/documentation/docs/offers/create.md index a5c6bb25..231daa04 100644 --- a/documentation/docs/offers/create.md +++ b/documentation/docs/offers/create.md @@ -13,6 +13,7 @@ import Highlight from "../../src/highlight.js" ## Details This endpoint is used to create offers. Both Admins and Companies can use it. +Companies which are yet to be approved will have its offer pending. :::info If the logged-in user is a Company, that account will be the Offer owner. Otherwise, the creation will be done in diff --git a/documentation/docs/offers/search.md b/documentation/docs/offers/search.md index f9e67689..aeb078b7 100644 --- a/documentation/docs/offers/search.md +++ b/documentation/docs/offers/search.md @@ -14,6 +14,7 @@ import Highlight from "../../src/highlight.js" This endpoint returns offers based on search criteria. It allows for _Full-Text Search_ as well as results filtering. Perfect for a search component! +Only returns offers that are not pending. **URL** : `/offers` @@ -271,6 +272,7 @@ values={[ "React Native" ], "isHidden": false, + "isPending": false, "isArchived": false, "requirements": [ "Recent graduate/master's degree in Computer Science, Engineering or similar areas" diff --git a/documentation/package-lock.json b/documentation/package-lock.json index cd042848..a52f01dc 100644 --- a/documentation/package-lock.json +++ b/documentation/package-lock.json @@ -96,7 +96,7 @@ "@algolia/transporter": "4.8.4" } }, - "@algolia/logger-common": { + "node_modules/@algolia/logger-common": { "version": "4.8.4", "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.8.4.tgz", "integrity": "sha512-6hOaFG75Onmant9adcaeCZgvPYfnif7n0H1ycbixm6/WH3SmxqPMG+CMiW8mTNTRrrAEceQVrq6tDHD8jdnOOw==" @@ -182,7 +182,15 @@ } } }, - "@babel/generator": { + "node_modules/@babel/core/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@babel/generator": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==", @@ -227,7 +235,15 @@ } } }, - "@babel/helper-create-class-features-plugin": { + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.12.1", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz", "integrity": "sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==", @@ -987,7 +1003,15 @@ } } }, - "@babel/plugin-transform-shorthand-properties": { + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { "version": "7.12.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz", "integrity": "sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw==", @@ -1135,7 +1159,15 @@ } } }, - "@babel/preset-modules": { + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@babel/preset-modules": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", @@ -1405,7 +1437,20 @@ } } }, - "@docusaurus/plugin-content-docs": { + "node_modules/@docusaurus/plugin-content-blog/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs": { "version": "2.0.0-alpha.70", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-alpha.70.tgz", "integrity": "sha512-LZre12Q0sxLgi2XgjQbNQMV+jFG7v0+8hRzgBL+iCRiLCa4NlV7+M6mEHJGJJXSKqbfH7CelaUOESqEgPpVQXQ==", @@ -1497,7 +1542,72 @@ } } }, - "@docusaurus/plugin-content-pages": { + "node_modules/@docusaurus/plugin-content-docs/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@docusaurus/plugin-content-pages": { "version": "2.0.0-alpha.70", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-alpha.70.tgz", "integrity": "sha512-HiFa5l1RDs155ATyYKkPtyIs/d6WJgSAyVfY5ji0Bsixp/K/Kh9YUZYMeTfeMIdhGYe3AAJz+PSZHYRpwTo1wA==", @@ -1537,7 +1647,20 @@ } } }, - "@docusaurus/plugin-debug": { + "node_modules/@docusaurus/plugin-content-pages/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@docusaurus/plugin-debug": { "version": "2.0.0-alpha.70", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-alpha.70.tgz", "integrity": "sha512-h/x5KtS/YJerhY6C6sJOaP9gMaSVnjj1qZ6r9E/IFujQJ7bSKnk1unqBQpVXADkQhP081ENPL01ubc0/JbE1Mw==", @@ -1720,7 +1843,7 @@ "@hapi/hoek": "^9.0.0" } }, - "@mdx-js/mdx": { + "node_modules/@mdx-js/mdx": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", @@ -1776,7 +1899,15 @@ } } }, - "@mdx-js/react": { + "node_modules/@mdx-js/mdx/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@mdx-js/react": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==" @@ -2370,19 +2501,24 @@ "@algolia/transporter": "4.8.4" } }, - "algoliasearch-helper": { + "node_modules/algoliasearch-helper": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.3.4.tgz", "integrity": "sha512-1Ts2XcgGdjGlDrp3v6zbY8VW+X9+jJ5rBmtPBmXOQLd4b5t/LpJlaBdxoAnlMfVFjywP7KSAdmyFUNNYVHDyRQ==", - "requires": { + "deprecated": "3.7.3", + "dependencies": { "events": "^1.1.1" }, - "dependencies": { - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" - } + "peerDependencies": { + "algoliasearch": ">= 3.1 < 5" + } + }, + "node_modules/algoliasearch-helper/node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "engines": { + "node": ">=0.4.x" } }, "alphanum-sort": { @@ -2435,12 +2571,26 @@ "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=" }, - "ansi-regex": { + "node_modules/ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "engines": { + "node": ">=6" + } }, - "ansi-styles": { + "node_modules/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==", @@ -2562,11 +2712,11 @@ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, - "async": { + "node_modules/async": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { + "dependencies": { "lodash": "^4.17.14" } }, @@ -2604,11 +2754,11 @@ "postcss-value-parser": "^4.1.0" } }, - "axios": { + "node_modules/axios": { "version": "0.21.1", "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", - "requires": { + "dependencies": { "follow-redirects": "^1.10.0" } }, @@ -2695,7 +2845,20 @@ } } }, - "babel-plugin-apply-mdx-type-prop": { + "node_modules/babel-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/babel-plugin-apply-mdx-type-prop": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz", "integrity": "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==", @@ -2816,7 +2979,7 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, - "bluebird": { + "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" @@ -2969,19 +3132,29 @@ "pako": "~1.0.5" } }, - "browserslist": { + "node_modules/browserslist": { "version": "4.16.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.1.tgz", "integrity": "sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==", - "requires": { + "dependencies": { "caniuse-lite": "^1.0.30001173", "colorette": "^1.2.1", "electron-to-chromium": "^1.3.634", "escalade": "^3.1.1", "node-releases": "^1.1.69" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" } }, - "buffer": { + "node_modules/buffer": { "version": "4.9.2", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", @@ -3096,7 +3269,20 @@ } } }, - "cacheable-request": { + "node_modules/cache-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/cacheable-request": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", @@ -3130,7 +3316,23 @@ } } }, - "call-bind": { + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", @@ -3202,7 +3404,7 @@ "lodash.uniq": "^4.5.0" } }, - "caniuse-lite": { + "node_modules/caniuse-lite": { "version": "1.0.30001181", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001181.tgz", "integrity": "sha512-m5ul/ARCX50JB8BSNM+oiPmQrR5UmngaQ3QThTTp5HcIIQGP/nPBs82BYLE+tigzm3VW+F4BJIhUyaVtEweelQ==" @@ -3286,7 +3488,7 @@ "version": "0.22.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", - "requires": { + "dependencies": { "css-select": "~1.2.0", "dom-serializer": "~0.1.0", "entities": "~1.1.1", @@ -3304,6 +3506,14 @@ "lodash.reject": "^4.4.0", "lodash.some": "^4.4.0" }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cheerio/node_modules/css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", "dependencies": { "css-select": { "version": "1.2.0", @@ -3470,7 +3680,18 @@ "tiny-emitter": "^2.0.0" } }, - "cliui": { + "node_modules/clipboard": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz", + "integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==", + "optional": true, + "dependencies": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, + "node_modules/cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", @@ -3563,11 +3784,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "color-string": { + "node_modules/color-string": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz", "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==", - "requires": { + "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } @@ -3819,11 +4040,11 @@ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" }, - "core-js-compat": { + "node_modules/core-js-compat": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.3.tgz", "integrity": "sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog==", - "requires": { + "dependencies": { "browserslist": "^4.16.1", "semver": "7.0.0" }, @@ -3835,7 +4056,15 @@ } } }, - "core-js-pure": { + "node_modules/core-js-compat/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/core-js-pure": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.8.3.tgz", "integrity": "sha512-V5qQZVAr9K0xu7jXg1M7qTEwuxUgqr7dUOezGaNa7i+Xn9oXAU/d1fzqD9ObuwpVQOaorO5s70ckyi1woP9lVA==" @@ -4061,7 +4290,20 @@ } } }, - "css-prefers-color-scheme": { + "node_modules/css-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/css-prefers-color-scheme": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz", "integrity": "sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==", @@ -4408,13 +4650,13 @@ } } }, - "delegate": { + "node_modules/delegate": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", "optional": true }, - "depd": { + "node_modules/depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" @@ -4495,11 +4737,11 @@ "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" }, - "dns-packet": { + "node_modules/dns-packet": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", - "requires": { + "dependencies": { "ip": "^1.1.0", "safe-buffer": "^5.0.1" } @@ -4635,16 +4877,16 @@ "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" }, - "electron-to-chromium": { + "node_modules/electron-to-chromium": { "version": "1.3.649", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.649.tgz", "integrity": "sha512-ojGDupQ3UMkvPWcTICe4JYe17+o9OLiFMPoduoR72Zp2ILt1mRVeqnxBEd6s/ptekrnsFU+0A4lStfBe/wyG/A==" }, - "elliptic": { + "node_modules/elliptic": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", - "requires": { + "dependencies": { "bn.js": "^4.4.0", "brorand": "^1.0.1", "hash.js": "^1.0.0", @@ -4652,13 +4894,6 @@ "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } } }, "emoji-regex": { @@ -4850,10 +5085,16 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, - "eta": { + "node_modules/eta": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/eta/-/eta-1.12.1.tgz", - "integrity": "sha512-H8npoci2J/7XiPnVcCVulBSPsTNGvGaINyMjQDU8AFqp9LGsEYS88g2CiU+d01Sg44WtX7o4nb8wUJ9vnI+tiA==" + "integrity": "sha512-H8npoci2J/7XiPnVcCVulBSPsTNGvGaINyMjQDU8AFqp9LGsEYS88g2CiU+d01Sg44WtX7o4nb8wUJ9vnI+tiA==", + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "url": "https://github.com/eta-dev/eta?sponsor=1" + } }, "etag": { "version": "1.8.1", @@ -4886,7 +5127,18 @@ "original": "^1.0.0" } }, - "evp_bytestokey": { + "node_modules/eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", + "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", + "dependencies": { + "original": "^1.0.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", @@ -4954,7 +5206,53 @@ } } }, - "expand-brackets": { + "node_modules/execa/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "engines": { + "node": ">=4" + } + }, + "node_modules/execa/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", @@ -5433,7 +5731,7 @@ } } }, - "filesize": { + "node_modules/filesize": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.0.1.tgz", "integrity": "sha512-u4AYWPgbI5GBhs6id1KdImZWn5yfyFrrQ8OWZdN7ZMfA8Bf4HcO0BGo9bmUIEV8yrp8I1xVfJ/dn90GtFNNJcg==" @@ -5512,10 +5810,24 @@ "fbjs": "^3.0.0" } }, - "follow-redirects": { + "node_modules/follow-redirects": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz", - "integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA==" + "integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } }, "for-in": { "version": "1.0.2", @@ -5668,7 +5980,144 @@ } } }, - "fragment-cache": { + "node_modules/fork-ts-checker-webpack-plugin/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/extend-shallow/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", @@ -5850,11 +6299,11 @@ "path-is-absolute": "^1.0.0" } }, - "glob-parent": { + "node_modules/glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "requires": { + "dependencies": { "is-glob": "^4.0.1" } }, @@ -5926,16 +6375,16 @@ "slash": "^3.0.0" } }, - "good-listener": { + "node_modules/good-listener": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", "optional": true, - "requires": { + "dependencies": { "delegate": "^3.1.2" } }, - "got": { + "node_modules/got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", @@ -6265,12 +6714,12 @@ "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=" }, - "html-comment-regex": { + "node_modules/html-comment-regex": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==" }, - "html-entities": { + "node_modules/html-entities": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==" @@ -6344,17 +6793,39 @@ } } }, - "htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "requires": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" + "node_modules/html-webpack-plugin/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/html-webpack-plugin/node_modules/util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dependencies": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "node_modules/htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" }, "dependencies": { "entities": { @@ -6716,6 +7187,22 @@ "strip-ansi": "^6.0.0", "through": "^2.3.6" }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/inquirer/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { "ansi-regex": { "version": "5.0.0", @@ -7097,7 +7584,18 @@ "html-comment-regex": "^1.1.0" } }, - "is-symbol": { + "node_modules/is-svg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", + "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", + "dependencies": { + "html-comment-regex": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", @@ -7298,11 +7796,11 @@ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==" }, - "loader-utils": { + "node_modules/loader-utils": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", - "requires": { + "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", "json5": "^2.1.2" @@ -7316,7 +7814,7 @@ "p-locate": "^4.1.0" } }, - "lodash": { + "node_modules/lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" @@ -7776,7 +8274,47 @@ } } }, - "minimalistic-assert": { + "node_modules/mini-css-extract-plugin/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "dependencies": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" @@ -7931,7 +8469,7 @@ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, - "nanomatch": { + "node_modules/nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", @@ -8148,7 +8686,33 @@ } } }, - "num2fraction": { + "node_modules/null-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/null-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" @@ -8317,15 +8881,15 @@ "last-call-webpack-plugin": "^3.0.0" } }, - "original": { + "node_modules/original": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", - "requires": { + "dependencies": { "url-parse": "^1.4.3" } }, - "os-browserify": { + "node_modules/os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" @@ -8544,7 +9108,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, - "path-parse": { + "node_modules/path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" @@ -8571,7 +9135,7 @@ "sha.js": "^2.4.8" } }, - "picomatch": { + "node_modules/picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" @@ -8675,49 +9239,21 @@ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, - "postcss": { + "node_modules/postcss": { "version": "7.0.35", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", - "requires": { + "dependencies": { "chalk": "^2.4.2", "source-map": "^0.6.1", "supports-color": "^6.1.0" }, - "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "requires": { - "has-flag": "^3.0.0" - } - } + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, "postcss-attribute-case-insensitive": { @@ -9117,7 +9653,33 @@ } } }, - "postcss-logical": { + "node_modules/postcss-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/postcss-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/postcss-logical": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz", "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==", @@ -9665,11 +10227,11 @@ "sort-css-media-queries": "1.5.0" } }, - "postcss-svgo": { + "node_modules/postcss-svgo": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", - "requires": { + "dependencies": { "is-svg": "^3.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0", @@ -9718,7 +10280,50 @@ "uniqs": "^2.0.0" } }, - "prepend-http": { + "node_modules/postcss/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss/node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/prepend-http": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" @@ -9750,7 +10355,15 @@ "clipboard": "^2.0.0" } }, - "process": { + "node_modules/prismjs": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz", + "integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==", + "optionalDependencies": { + "clipboard": "^2.0.0" + } + }, + "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" @@ -10316,105 +10929,515 @@ } } }, - "react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" + "node_modules/react-dev-utils/node_modules/@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "engines": { + "node": ">= 6" } }, - "react-error-overlay": { - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.8.tgz", - "integrity": "sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw==" - }, - "react-fast-compare": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", - "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" - }, - "react-helmet": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", - "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==", - "requires": { - "object-assign": "^4.1.1", - "prop-types": "^15.7.2", - "react-fast-compare": "^3.1.1", - "react-side-effect": "^2.1.0" + "node_modules/react-dev-utils/node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "node_modules/react-dev-utils/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } }, - "react-json-view": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/react-json-view/-/react-json-view-1.20.4.tgz", - "integrity": "sha512-QBhb1STnWif+wY8Bsl+ISyDnKTocN/37gSauq8MNHjvu7UOLmdTAgynnC5/rrPh1sAdakg7oIhxU0l660xQg+Q==", - "requires": { - "flux": "^4.0.1", - "react-base16-styling": "^0.6.0", - "react-lifecycles-compat": "^3.0.4", - "react-textarea-autosize": "^6.1.0" + "node_modules/react-dev-utils/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "react-lifecycles-compat": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + "node_modules/react-dev-utils/node_modules/browserslist": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.10.0.tgz", + "integrity": "sha512-TpfK0TDgv71dzuTsEAlQiHeWQ/tiPqgNZVdv046fvNtBZrjbv2O3TsWCDU0AWGJJKCF/KsjNdLzR9hXOsh/CfA==", + "dependencies": { + "caniuse-lite": "^1.0.30001035", + "electron-to-chromium": "^1.3.378", + "node-releases": "^1.1.52", + "pkg-up": "^3.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } }, - "react-loadable": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/react-loadable/-/react-loadable-5.5.0.tgz", - "integrity": "sha512-C8Aui0ZpMd4KokxRdVAm2bQtI03k2RMRNzOB+IipV3yxFTSVICv7WoUr5L9ALB5BmKO1iHgZtWM8EvYG83otdg==", - "requires": { - "prop-types": "^15.5.0" + "node_modules/react-dev-utils/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "react-loadable-ssr-addon": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon/-/react-loadable-ssr-addon-0.3.0.tgz", - "integrity": "sha512-E+lnmDakV0k6ut6R2J77vurwCOwTKEwKlHs9S62G8ez+ujecLPcqjt3YAU8M58kIGjp2QjFlZ7F9QWkq/mr6Iw==", - "requires": { - "@babel/runtime": "^7.10.3" + "node_modules/react-dev-utils/node_modules/chalk/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "engines": { + "node": ">=0.8.0" } }, - "react-router": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", - "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", - "requires": { - "@babel/runtime": "^7.1.2", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "mini-create-react-context": "^0.4.0", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" - }, + "node_modules/react-dev-utils/node_modules/cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==" + }, + "node_modules/react-dev-utils/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "requires": { - "isarray": "0.0.1" - } - } + "ms": "2.0.0" + } + }, + "node_modules/react-dev-utils/node_modules/detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/react-dev-utils/node_modules/dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "dependencies": { + "arrify": "^1.0.1", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/react-dev-utils/node_modules/emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/react-dev-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/react-dev-utils/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dev-utils/node_modules/extend-shallow/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dev-utils/node_modules/fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dependencies": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/react-dev-utils/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dev-utils/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dev-utils/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/react-dev-utils/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dev-utils/node_modules/globby": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", + "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", + "dependencies": { + "array-union": "^1.0.1", + "dir-glob": "2.0.0", + "fast-glob": "^2.0.2", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/react-dev-utils/node_modules/ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" + }, + "node_modules/react-dev-utils/node_modules/inquirer": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.4.tgz", + "integrity": "sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.2", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.2.0", + "rxjs": "^6.5.3", + "string-width": "^4.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/react-dev-utils/node_modules/inquirer/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/react-dev-utils/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dev-utils/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dev-utils/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/react-dev-utils/node_modules/loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/react-dev-utils/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dev-utils/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/react-dev-utils/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/react-dev-utils/node_modules/slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dev-utils/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/react-dev-utils/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/react-dev-utils/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + } + }, + "react-error-overlay": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.8.tgz", + "integrity": "sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw==" + }, + "react-fast-compare": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", + "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" + }, + "react-helmet": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", + "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==", + "requires": { + "object-assign": "^4.1.1", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.1.1", + "react-side-effect": "^2.1.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "react-json-view": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/react-json-view/-/react-json-view-1.20.4.tgz", + "integrity": "sha512-QBhb1STnWif+wY8Bsl+ISyDnKTocN/37gSauq8MNHjvu7UOLmdTAgynnC5/rrPh1sAdakg7oIhxU0l660xQg+Q==", + "requires": { + "flux": "^4.0.1", + "react-base16-styling": "^0.6.0", + "react-lifecycles-compat": "^3.0.4", + "react-textarea-autosize": "^6.1.0" + } + }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "react-loadable": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-loadable/-/react-loadable-5.5.0.tgz", + "integrity": "sha512-C8Aui0ZpMd4KokxRdVAm2bQtI03k2RMRNzOB+IipV3yxFTSVICv7WoUr5L9ALB5BmKO1iHgZtWM8EvYG83otdg==", + "requires": { + "prop-types": "^15.5.0" + } + }, + "react-loadable-ssr-addon": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon/-/react-loadable-ssr-addon-0.3.0.tgz", + "integrity": "sha512-E+lnmDakV0k6ut6R2J77vurwCOwTKEwKlHs9S62G8ez+ujecLPcqjt3YAU8M58kIGjp2QjFlZ7F9QWkq/mr6Iw==", + "requires": { + "@babel/runtime": "^7.10.3" + } + }, + "react-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", + "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + } } }, "react-router-config": { @@ -10745,7 +11768,15 @@ } } }, - "remark-parse": { + "node_modules/remark-mdx/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/remark-parse": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", @@ -10781,34 +11812,38 @@ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, - "renderkid": { + "node_modules/renderkid": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.5.tgz", "integrity": "sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ==", - "requires": { + "dependencies": { "css-select": "^2.0.2", "dom-converter": "^0.2", "htmlparser2": "^3.10.1", "lodash": "^4.17.20", "strip-ansi": "^3.0.0" - }, + } + }, + "node_modules/renderkid/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/renderkid/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - } + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "repeat-element": { + "node_modules/repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" @@ -11020,29 +12055,32 @@ "kind-of": "^6.0.0" } }, - "select": { + "node_modules/select": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=", "optional": true }, - "select-hose": { + "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" }, - "selfsigned": { + "node_modules/selfsigned": { "version": "1.10.8", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", - "requires": { + "dependencies": { "node-forge": "^0.10.0" } }, - "semver": { + "node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } }, "semver-diff": { "version": "3.1.1", @@ -11060,11 +12098,11 @@ "randombytes": "^2.1.0" } }, - "serve-handler": { + "node_modules/serve-handler": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", - "requires": { + "dependencies": { "bytes": "3.0.0", "content-disposition": "0.5.2", "fast-url-parser": "1.1.3", @@ -11074,43 +12112,24 @@ "path-to-regexp": "2.2.1", "range-parser": "1.2.0" }, - "dependencies": { - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" - }, - "mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" - }, - "mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "requires": { - "mime-db": "~1.33.0" - } - }, - "path-to-regexp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", - "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" - } + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-handler/node_modules/path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + }, + "node_modules/serve-handler/node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "engines": { + "node": ">= 0.6" } }, - "serve-index": { + "node_modules/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", @@ -11208,11 +12227,11 @@ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" }, - "shelljs": { + "node_modules/shelljs": { "version": "0.8.4", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", - "requires": { + "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", "rechoir": "^0.6.2" @@ -11427,11 +12446,11 @@ "urix": "^0.1.0" } }, - "source-map-support": { + "node_modules/source-map-support": { "version": "0.5.19", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "requires": { + "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" }, @@ -11657,6 +12676,35 @@ "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.0" }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dependencies": { "ansi-regex": { "version": "5.0.0", @@ -11841,11 +12889,11 @@ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" }, - "tar": { + "node_modules/tar": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", - "requires": { + "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^3.0.0", @@ -11853,24 +12901,31 @@ "mkdirp": "^1.0.3", "yallist": "^4.0.0" }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - } + "engines": { + "node": ">= 10" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" } }, - "term-size": { + "node_modules/term-size": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==" }, - "terser": { + "node_modules/terser": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "requires": { + "dependencies": { "commander": "^2.20.0", "source-map": "~0.6.1", "source-map-support": "~0.5.12" @@ -11903,6 +12958,26 @@ "terser": "^5.3.4", "webpack-sources": "^1.4.3" }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/terser-webpack-plugin/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dependencies": { "commander": { "version": "2.20.3", @@ -11951,7 +13026,69 @@ } } }, - "text-table": { + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/terser": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz", + "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==", + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin/node_modules/terser/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" @@ -12012,13 +13149,13 @@ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" }, - "tiny-emitter": { + "node_modules/tiny-emitter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", "optional": true }, - "tiny-invariant": { + "node_modules/tiny-invariant": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" @@ -12125,7 +13262,8 @@ "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "deprecated": "Use String.prototype.trim() instead" }, "trim-trailing-lines": { "version": "1.1.4", @@ -12411,7 +13549,7 @@ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" }, - "update-notifier": { + "node_modules/update-notifier": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", @@ -12482,11 +13620,28 @@ } } }, - "url-parse": { + "node_modules/url-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/url-parse": { "version": "1.4.7", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", - "requires": { + "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } @@ -12910,7 +14065,245 @@ } } }, - "wbuf": { + "node_modules/watchpack-chokidar2/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "optional": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "optional": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/watchpack-chokidar2/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "optional": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/extend-shallow/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "optional": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "optional": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "optional": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "optional": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "optional": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "optional": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "optional": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "optional": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "optional": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "optional": true, + "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/watchpack-chokidar2/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "optional": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/watchpack-chokidar2/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==", + "optional": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "optional": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wbuf": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", @@ -13317,19 +14710,29 @@ "range-parser": "^1.2.1", "webpack-log": "^2.0.0" }, - "dependencies": { - "mime": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz", - "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==" - } + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz", + "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" } }, - "webpack-dev-server": { + "node_modules/webpack-dev-server": { "version": "3.11.2", "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz", "integrity": "sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ==", - "requires": { + "dependencies": { "ansi-html": "0.0.7", "bonjour": "^3.5.0", "chokidar": "^2.1.8", @@ -13684,21 +15087,420 @@ } } }, - "webpack-log": { + "node_modules/webpack-dev-server/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/anymatch": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", - "requires": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" } }, - "webpack-merge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", - "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", - "requires": { - "lodash": "^4.17.15" + "node_modules/webpack-dev-server/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/webpack-dev-server/node_modules/del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dependencies": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/extend-shallow/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/webpack-dev-server/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/webpack-dev-server/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/globby/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack-dev-server/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "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/webpack-dev-server/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/webpack-dev-server/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/webpack-dev-server/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/webpack-dev-server/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", + "requires": { + "lodash": "^4.17.15" } }, "webpack-sources": { @@ -13717,7 +15519,348 @@ } } }, - "webpackbar": { + "node_modules/webpack/node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/webpack/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/webpack/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/extend-shallow/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/webpack/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/webpack/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/webpack/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/webpack/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "engines": { + "node": ">=4" + } + }, + "node_modules/webpack/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/webpack/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/webpack/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/webpack/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/webpack/node_modules/terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dependencies": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/webpack/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/webpackbar": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-4.0.0.tgz", "integrity": "sha512-k1qRoSL/3BVuINzngj09nIwreD8wxV4grcuhHTD8VJgUbGcy8lQSPqv+bM00B7F+PffwIsQ8ISd4mIwRbr23eQ==", @@ -13731,6 +15874,25 @@ "text-table": "^0.2.0", "wrap-ansi": "^6.0.0" }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "webpack": "^3.0.0 || ^4.0.0" + } + }, + "node_modules/webpackbar/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/webpackbar/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { "ansi-regex": { "version": "5.0.0", @@ -13890,11 +16052,11 @@ "typedarray-to-buffer": "^3.1.5" } }, - "ws": { + "node_modules/ws": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "requires": { + "dependencies": { "async-limiter": "~1.0.0" } }, @@ -14022,4 +16184,4 @@ "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==" } } -} +} \ No newline at end of file diff --git a/documentation/package.json b/documentation/package.json index 6a91ec85..5938a896 100644 --- a/documentation/package.json +++ b/documentation/package.json @@ -31,4 +31,4 @@ "last 1 safari version" ] } -} +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 82755ce3..ef9ff903 100644 --- a/package-lock.json +++ b/package-lock.json @@ -58,9 +58,27 @@ "node": ">=6.0.0" } }, + "node_modules/@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "optional": true, + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/crc32/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "optional": true + }, "node_modules/@aws-crypto/ie11-detection": { - "version": "2.0.2", - "license": "Apache-2.0", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", "optional": true, "dependencies": { "tslib": "^1.11.1" @@ -68,19 +86,21 @@ }, "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { "version": "1.14.1", - "license": "0BSD", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true }, "node_modules/@aws-crypto/sha256-browser": { - "version": "2.0.0", - "license": "Apache-2.0", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", "optional": true, "dependencies": { - "@aws-crypto/ie11-detection": "^2.0.0", - "@aws-crypto/sha256-js": "^2.0.0", - "@aws-crypto/supports-web-crypto": "^2.0.0", - "@aws-crypto/util": "^2.0.0", - "@aws-sdk/types": "^3.1.0", + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@aws-sdk/util-utf8-browser": "^3.0.0", "tslib": "^1.11.1" @@ -88,27 +108,31 @@ }, "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { "version": "1.14.1", - "license": "0BSD", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true }, "node_modules/@aws-crypto/sha256-js": { - "version": "2.0.0", - "license": "Apache-2.0", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", "optional": true, "dependencies": { - "@aws-crypto/util": "^2.0.0", - "@aws-sdk/types": "^3.1.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", "tslib": "^1.11.1" } }, "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { "version": "1.14.1", - "license": "0BSD", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true }, "node_modules/@aws-crypto/supports-web-crypto": { - "version": "2.0.2", - "license": "Apache-2.0", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", "optional": true, "dependencies": { "tslib": "^1.11.1" @@ -116,1445 +140,1362 @@ }, "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { "version": "1.14.1", - "license": "0BSD", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true }, "node_modules/@aws-crypto/util": { - "version": "2.0.2", - "license": "Apache-2.0", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", "optional": true, "dependencies": { - "@aws-sdk/types": "^3.110.0", + "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-utf8-browser": "^3.0.0", "tslib": "^1.11.1" } }, "node_modules/@aws-crypto/util/node_modules/tslib": { "version": "1.14.1", - "license": "0BSD", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true }, - "node_modules/@aws-sdk/abort-controller": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.229.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-crypto/sha256-browser": "2.0.0", - "@aws-crypto/sha256-js": "2.0.0", - "@aws-sdk/client-sts": "3.229.0", - "@aws-sdk/config-resolver": "3.226.0", - "@aws-sdk/credential-provider-node": "3.229.0", - "@aws-sdk/fetch-http-handler": "3.226.0", - "@aws-sdk/hash-node": "3.226.0", - "@aws-sdk/invalid-dependency": "3.226.0", - "@aws-sdk/middleware-content-length": "3.226.0", - "@aws-sdk/middleware-endpoint": "3.226.0", - "@aws-sdk/middleware-host-header": "3.226.0", - "@aws-sdk/middleware-logger": "3.226.0", - "@aws-sdk/middleware-recursion-detection": "3.226.0", - "@aws-sdk/middleware-retry": "3.229.0", - "@aws-sdk/middleware-serde": "3.226.0", - "@aws-sdk/middleware-signing": "3.226.0", - "@aws-sdk/middleware-stack": "3.226.0", - "@aws-sdk/middleware-user-agent": "3.226.0", - "@aws-sdk/node-config-provider": "3.226.0", - "@aws-sdk/node-http-handler": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/smithy-client": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/url-parser": "3.226.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.226.0", - "@aws-sdk/util-defaults-mode-node": "3.226.0", - "@aws-sdk/util-endpoints": "3.226.0", - "@aws-sdk/util-retry": "3.229.0", - "@aws-sdk/util-user-agent-browser": "3.226.0", - "@aws-sdk/util-user-agent-node": "3.226.0", - "@aws-sdk/util-utf8-browser": "3.188.0", - "@aws-sdk/util-utf8-node": "3.208.0", - "tslib": "^2.3.1" + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.398.0.tgz", + "integrity": "sha512-Pr/S1f8R2FsJ8DwBC6g0CSdtZNNV5dMHhlIi+t8YAmCJvP4KT+UhzFjbvQRINlBRLFuGUuP7p5vRcGVELD3+wA==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.398.0", + "@aws-sdk/credential-provider-node": "3.398.0", + "@aws-sdk/middleware-host-header": "3.398.0", + "@aws-sdk/middleware-logger": "3.398.0", + "@aws-sdk/middleware-recursion-detection": "3.398.0", + "@aws-sdk/middleware-signing": "3.398.0", + "@aws-sdk/middleware-user-agent": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@aws-sdk/util-endpoints": "3.398.0", + "@aws-sdk/util-user-agent-browser": "3.398.0", + "@aws-sdk/util-user-agent-node": "3.398.0", + "@smithy/config-resolver": "^2.0.5", + "@smithy/fetch-http-handler": "^2.0.5", + "@smithy/hash-node": "^2.0.5", + "@smithy/invalid-dependency": "^2.0.5", + "@smithy/middleware-content-length": "^2.0.5", + "@smithy/middleware-endpoint": "^2.0.5", + "@smithy/middleware-retry": "^2.0.5", + "@smithy/middleware-serde": "^2.0.5", + "@smithy/middleware-stack": "^2.0.0", + "@smithy/node-config-provider": "^2.0.5", + "@smithy/node-http-handler": "^2.0.5", + "@smithy/protocol-http": "^2.0.5", + "@smithy/smithy-client": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/url-parser": "^2.0.5", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.5", + "@smithy/util-defaults-mode-node": "^2.0.5", + "@smithy/util-retry": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.229.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-crypto/sha256-browser": "2.0.0", - "@aws-crypto/sha256-js": "2.0.0", - "@aws-sdk/config-resolver": "3.226.0", - "@aws-sdk/fetch-http-handler": "3.226.0", - "@aws-sdk/hash-node": "3.226.0", - "@aws-sdk/invalid-dependency": "3.226.0", - "@aws-sdk/middleware-content-length": "3.226.0", - "@aws-sdk/middleware-endpoint": "3.226.0", - "@aws-sdk/middleware-host-header": "3.226.0", - "@aws-sdk/middleware-logger": "3.226.0", - "@aws-sdk/middleware-recursion-detection": "3.226.0", - "@aws-sdk/middleware-retry": "3.229.0", - "@aws-sdk/middleware-serde": "3.226.0", - "@aws-sdk/middleware-stack": "3.226.0", - "@aws-sdk/middleware-user-agent": "3.226.0", - "@aws-sdk/node-config-provider": "3.226.0", - "@aws-sdk/node-http-handler": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/smithy-client": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/url-parser": "3.226.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.226.0", - "@aws-sdk/util-defaults-mode-node": "3.226.0", - "@aws-sdk/util-endpoints": "3.226.0", - "@aws-sdk/util-retry": "3.229.0", - "@aws-sdk/util-user-agent-browser": "3.226.0", - "@aws-sdk/util-user-agent-node": "3.226.0", - "@aws-sdk/util-utf8-browser": "3.188.0", - "@aws-sdk/util-utf8-node": "3.208.0", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.229.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-crypto/sha256-browser": "2.0.0", - "@aws-crypto/sha256-js": "2.0.0", - "@aws-sdk/config-resolver": "3.226.0", - "@aws-sdk/fetch-http-handler": "3.226.0", - "@aws-sdk/hash-node": "3.226.0", - "@aws-sdk/invalid-dependency": "3.226.0", - "@aws-sdk/middleware-content-length": "3.226.0", - "@aws-sdk/middleware-endpoint": "3.226.0", - "@aws-sdk/middleware-host-header": "3.226.0", - "@aws-sdk/middleware-logger": "3.226.0", - "@aws-sdk/middleware-recursion-detection": "3.226.0", - "@aws-sdk/middleware-retry": "3.229.0", - "@aws-sdk/middleware-serde": "3.226.0", - "@aws-sdk/middleware-stack": "3.226.0", - "@aws-sdk/middleware-user-agent": "3.226.0", - "@aws-sdk/node-config-provider": "3.226.0", - "@aws-sdk/node-http-handler": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/smithy-client": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/url-parser": "3.226.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.226.0", - "@aws-sdk/util-defaults-mode-node": "3.226.0", - "@aws-sdk/util-endpoints": "3.226.0", - "@aws-sdk/util-retry": "3.229.0", - "@aws-sdk/util-user-agent-browser": "3.226.0", - "@aws-sdk/util-user-agent-node": "3.226.0", - "@aws-sdk/util-utf8-browser": "3.188.0", - "@aws-sdk/util-utf8-node": "3.208.0", - "tslib": "^2.3.1" + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.398.0.tgz", + "integrity": "sha512-CygL0jhfibw4kmWXG/3sfZMFNjcXo66XUuPC4BqZBk8Rj5vFoxp1vZeMkDLzTIk97Nvo5J5Bh+QnXKhub6AckQ==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.398.0", + "@aws-sdk/middleware-logger": "3.398.0", + "@aws-sdk/middleware-recursion-detection": "3.398.0", + "@aws-sdk/middleware-user-agent": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@aws-sdk/util-endpoints": "3.398.0", + "@aws-sdk/util-user-agent-browser": "3.398.0", + "@aws-sdk/util-user-agent-node": "3.398.0", + "@smithy/config-resolver": "^2.0.5", + "@smithy/fetch-http-handler": "^2.0.5", + "@smithy/hash-node": "^2.0.5", + "@smithy/invalid-dependency": "^2.0.5", + "@smithy/middleware-content-length": "^2.0.5", + "@smithy/middleware-endpoint": "^2.0.5", + "@smithy/middleware-retry": "^2.0.5", + "@smithy/middleware-serde": "^2.0.5", + "@smithy/middleware-stack": "^2.0.0", + "@smithy/node-config-provider": "^2.0.5", + "@smithy/node-http-handler": "^2.0.5", + "@smithy/protocol-http": "^2.0.5", + "@smithy/smithy-client": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/url-parser": "^2.0.5", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.5", + "@smithy/util-defaults-mode-node": "^2.0.5", + "@smithy/util-retry": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.229.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-crypto/sha256-browser": "2.0.0", - "@aws-crypto/sha256-js": "2.0.0", - "@aws-sdk/config-resolver": "3.226.0", - "@aws-sdk/credential-provider-node": "3.229.0", - "@aws-sdk/fetch-http-handler": "3.226.0", - "@aws-sdk/hash-node": "3.226.0", - "@aws-sdk/invalid-dependency": "3.226.0", - "@aws-sdk/middleware-content-length": "3.226.0", - "@aws-sdk/middleware-endpoint": "3.226.0", - "@aws-sdk/middleware-host-header": "3.226.0", - "@aws-sdk/middleware-logger": "3.226.0", - "@aws-sdk/middleware-recursion-detection": "3.226.0", - "@aws-sdk/middleware-retry": "3.229.0", - "@aws-sdk/middleware-sdk-sts": "3.226.0", - "@aws-sdk/middleware-serde": "3.226.0", - "@aws-sdk/middleware-signing": "3.226.0", - "@aws-sdk/middleware-stack": "3.226.0", - "@aws-sdk/middleware-user-agent": "3.226.0", - "@aws-sdk/node-config-provider": "3.226.0", - "@aws-sdk/node-http-handler": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/smithy-client": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/url-parser": "3.226.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.226.0", - "@aws-sdk/util-defaults-mode-node": "3.226.0", - "@aws-sdk/util-endpoints": "3.226.0", - "@aws-sdk/util-retry": "3.229.0", - "@aws-sdk/util-user-agent-browser": "3.226.0", - "@aws-sdk/util-user-agent-node": "3.226.0", - "@aws-sdk/util-utf8-browser": "3.188.0", - "@aws-sdk/util-utf8-node": "3.208.0", - "fast-xml-parser": "4.0.11", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/config-resolver": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-sdk/signature-v4": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/util-config-provider": "3.208.0", - "@aws-sdk/util-middleware": "3.226.0", - "tslib": "^2.3.1" + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.398.0.tgz", + "integrity": "sha512-/3Pa9wLMvBZipKraq3AtbmTfXW6q9kyvhwOno64f1Fz7kFb8ijQFMGoATS70B2pGEZTlxkUqJFWDiisT6Q6dFg==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/credential-provider-node": "3.398.0", + "@aws-sdk/middleware-host-header": "3.398.0", + "@aws-sdk/middleware-logger": "3.398.0", + "@aws-sdk/middleware-recursion-detection": "3.398.0", + "@aws-sdk/middleware-sdk-sts": "3.398.0", + "@aws-sdk/middleware-signing": "3.398.0", + "@aws-sdk/middleware-user-agent": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@aws-sdk/util-endpoints": "3.398.0", + "@aws-sdk/util-user-agent-browser": "3.398.0", + "@aws-sdk/util-user-agent-node": "3.398.0", + "@smithy/config-resolver": "^2.0.5", + "@smithy/fetch-http-handler": "^2.0.5", + "@smithy/hash-node": "^2.0.5", + "@smithy/invalid-dependency": "^2.0.5", + "@smithy/middleware-content-length": "^2.0.5", + "@smithy/middleware-endpoint": "^2.0.5", + "@smithy/middleware-retry": "^2.0.5", + "@smithy/middleware-serde": "^2.0.5", + "@smithy/middleware-stack": "^2.0.0", + "@smithy/node-config-provider": "^2.0.5", + "@smithy/node-http-handler": "^2.0.5", + "@smithy/protocol-http": "^2.0.5", + "@smithy/smithy-client": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/url-parser": "^2.0.5", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.5", + "@smithy/util-defaults-mode-node": "^2.0.5", + "@smithy/util-retry": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.229.0", - "license": "Apache-2.0", + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.398.0.tgz", + "integrity": "sha512-MFUhy1YayHg5ypRTk4OTfDumQRP+OJBagaGv14kA8DzhKH1sNrU4HV7A7y2J4SvkN5hG/KnLJqxpakCtB2/O2g==", "optional": true, "dependencies": { - "@aws-sdk/client-cognito-identity": "3.229.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/client-cognito-identity": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-imds": { - "version": "3.226.0", - "license": "Apache-2.0", + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.398.0.tgz", + "integrity": "sha512-Z8Yj5z7FroAsR6UVML+XUdlpoqEe9Dnle8c2h8/xWwIC2feTfIBhjLhRVxfbpbM1pLgBSNEcZ7U8fwq5l7ESVQ==", "optional": true, "dependencies": { - "@aws-sdk/node-config-provider": "3.226.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/url-parser": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.229.0", - "license": "Apache-2.0", + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.398.0.tgz", + "integrity": "sha512-AsK1lStK3nB9Cn6S6ODb1ktGh7SRejsNVQVKX3t5d3tgOaX+aX1Iwy8FzM/ZEN8uCloeRifUGIY9uQFygg5mSw==", "optional": true, "dependencies": { - "@aws-sdk/credential-provider-env": "3.226.0", - "@aws-sdk/credential-provider-imds": "3.226.0", - "@aws-sdk/credential-provider-sso": "3.229.0", - "@aws-sdk/credential-provider-web-identity": "3.226.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/shared-ini-file-loader": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/credential-provider-env": "3.398.0", + "@aws-sdk/credential-provider-process": "3.398.0", + "@aws-sdk/credential-provider-sso": "3.398.0", + "@aws-sdk/credential-provider-web-identity": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.229.0", - "license": "Apache-2.0", + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.398.0.tgz", + "integrity": "sha512-odmI/DSKfuWUYeDnGTCEHBbC8/MwnF6yEq874zl6+owoVv0ZsYP8qBHfiJkYqrwg7wQ7Pi40sSAPC1rhesGwzg==", "optional": true, "dependencies": { - "@aws-sdk/credential-provider-env": "3.226.0", - "@aws-sdk/credential-provider-imds": "3.226.0", - "@aws-sdk/credential-provider-ini": "3.229.0", - "@aws-sdk/credential-provider-process": "3.226.0", - "@aws-sdk/credential-provider-sso": "3.229.0", - "@aws-sdk/credential-provider-web-identity": "3.226.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/shared-ini-file-loader": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/credential-provider-env": "3.398.0", + "@aws-sdk/credential-provider-ini": "3.398.0", + "@aws-sdk/credential-provider-process": "3.398.0", + "@aws-sdk/credential-provider-sso": "3.398.0", + "@aws-sdk/credential-provider-web-identity": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.226.0", - "license": "Apache-2.0", + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.398.0.tgz", + "integrity": "sha512-WrkBL1W7TXN508PA9wRXPFtzmGpVSW98gDaHEaa8GolAPHMPa5t2QcC/z/cFpglzrcVv8SA277zu9Z8tELdZhg==", "optional": true, "dependencies": { - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/shared-ini-file-loader": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.229.0", - "license": "Apache-2.0", + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.398.0.tgz", + "integrity": "sha512-2Dl35587xbnzR/GGZqA2MnFs8+kS4wbHQO9BioU0okA+8NRueohNMdrdQmQDdSNK4BfIpFspiZmFkXFNyEAfgw==", "optional": true, "dependencies": { - "@aws-sdk/client-sso": "3.229.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/shared-ini-file-loader": "3.226.0", - "@aws-sdk/token-providers": "3.229.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/client-sso": "3.398.0", + "@aws-sdk/token-providers": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.226.0", - "license": "Apache-2.0", + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.398.0.tgz", + "integrity": "sha512-iG3905Alv9pINbQ8/MIsshgqYMbWx+NDQWpxbIW3W0MkSH3iAqdVpSCteYidYX9G/jv2Um1nW3y360ib20bvNg==", "optional": true, "dependencies": { - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-providers": { - "version": "3.229.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-sdk/client-cognito-identity": "3.229.0", - "@aws-sdk/client-sso": "3.229.0", - "@aws-sdk/client-sts": "3.229.0", - "@aws-sdk/credential-provider-cognito-identity": "3.229.0", - "@aws-sdk/credential-provider-env": "3.226.0", - "@aws-sdk/credential-provider-imds": "3.226.0", - "@aws-sdk/credential-provider-ini": "3.229.0", - "@aws-sdk/credential-provider-node": "3.229.0", - "@aws-sdk/credential-provider-process": "3.226.0", - "@aws-sdk/credential-provider-sso": "3.229.0", - "@aws-sdk/credential-provider-web-identity": "3.226.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/shared-ini-file-loader": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.398.0.tgz", + "integrity": "sha512-355vXmImn2e85mIWSYDVb101AF2lIVHKNCaH6sV1U/8i0ZOXh2cJYNdkRYrxNt1ezDB0k97lSKvuDx7RDvJyRg==", + "optional": true, + "dependencies": { + "@aws-sdk/client-cognito-identity": "3.398.0", + "@aws-sdk/client-sso": "3.398.0", + "@aws-sdk/client-sts": "3.398.0", + "@aws-sdk/credential-provider-cognito-identity": "3.398.0", + "@aws-sdk/credential-provider-env": "3.398.0", + "@aws-sdk/credential-provider-ini": "3.398.0", + "@aws-sdk/credential-provider-node": "3.398.0", + "@aws-sdk/credential-provider-process": "3.398.0", + "@aws-sdk/credential-provider-sso": "3.398.0", + "@aws-sdk/credential-provider-web-identity": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/fetch-http-handler": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/querystring-builder": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/util-base64": "3.208.0", - "tslib": "^2.3.1" - } - }, - "node_modules/@aws-sdk/hash-node": { - "version": "3.226.0", - "license": "Apache-2.0", + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.398.0.tgz", + "integrity": "sha512-m+5laWdBaxIZK2ko0OwcCHJZJ5V1MgEIt8QVQ3k4/kOkN9ICjevOYmba751pHoTnbOYB7zQd6D2OT3EYEEsUcA==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.226.0", - "@aws-sdk/util-buffer-from": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/protocol-http": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/invalid-dependency": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "node_modules/@aws-sdk/is-array-buffer": { - "version": "3.201.0", - "license": "Apache-2.0", + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.398.0.tgz", + "integrity": "sha512-CiJjW+FL12elS6Pn7/UVjVK8HWHhXMfvHZvOwx/Qkpy340sIhkuzOO6fZEruECDTZhl2Wqn81XdJ1ZQ4pRKpCg==", "optional": true, "dependencies": { - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/middleware-content-length": { - "version": "3.226.0", - "license": "Apache-2.0", + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.398.0.tgz", + "integrity": "sha512-7QpOqPQAZNXDXv6vsRex4R8dLniL0E/80OPK4PPFsrCh9btEyhN9Begh4i1T+5lL28hmYkztLOkTQ2N5J3hgRQ==", "optional": true, "dependencies": { - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/protocol-http": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/middleware-endpoint": { - "version": "3.226.0", - "license": "Apache-2.0", + "node_modules/@aws-sdk/middleware-sdk-sts": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.398.0.tgz", + "integrity": "sha512-+JH76XHEgfVihkY+GurohOQ5Z83zVN1nYcQzwCFnCDTh4dG4KwhnZKG+WPw6XJECocY0R+H0ivofeALHvVWJtQ==", "optional": true, "dependencies": { - "@aws-sdk/middleware-serde": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/signature-v4": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/url-parser": "3.226.0", - "@aws-sdk/util-config-provider": "3.208.0", - "@aws-sdk/util-middleware": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/middleware-signing": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.226.0", - "license": "Apache-2.0", + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.398.0.tgz", + "integrity": "sha512-O0KqXAix1TcvZBFt1qoFkHMUNJOSgjJTYS7lFTRKSwgsD27bdW2TM2r9R8DAccWFt5Amjkdt+eOwQMIXPGTm8w==", "optional": true, "dependencies": { - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^2.0.5", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.2.2", + "@smithy/util-middleware": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.226.0", - "license": "Apache-2.0", + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.398.0.tgz", + "integrity": "sha512-nF1jg0L+18b5HvTcYzwyFgfZQQMELJINFqI0mi4yRKaX7T5a3aGp5RVLGGju/6tAGTuFbfBoEhkhU3kkxexPYQ==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@aws-sdk/util-endpoints": "3.398.0", + "@smithy/protocol-http": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "node_modules/@aws-sdk/token-providers": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.398.0.tgz", + "integrity": "sha512-nrYgjzavGCKJL/48Vt0EL+OlIc5UZLfNGpgyUW9cv3XZwl+kXV0QB+HH0rHZZLfpbBgZ2RBIJR9uD5ieu/6hpQ==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.398.0", + "@aws-sdk/middleware-logger": "3.398.0", + "@aws-sdk/middleware-recursion-detection": "3.398.0", + "@aws-sdk/middleware-user-agent": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@aws-sdk/util-endpoints": "3.398.0", + "@aws-sdk/util-user-agent-browser": "3.398.0", + "@aws-sdk/util-user-agent-node": "3.398.0", + "@smithy/config-resolver": "^2.0.5", + "@smithy/fetch-http-handler": "^2.0.5", + "@smithy/hash-node": "^2.0.5", + "@smithy/invalid-dependency": "^2.0.5", + "@smithy/middleware-content-length": "^2.0.5", + "@smithy/middleware-endpoint": "^2.0.5", + "@smithy/middleware-retry": "^2.0.5", + "@smithy/middleware-serde": "^2.0.5", + "@smithy/middleware-stack": "^2.0.0", + "@smithy/node-config-provider": "^2.0.5", + "@smithy/node-http-handler": "^2.0.5", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^2.0.5", + "@smithy/shared-ini-file-loader": "^2.0.0", + "@smithy/smithy-client": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/url-parser": "^2.0.5", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.5", + "@smithy/util-defaults-mode-node": "^2.0.5", + "@smithy/util-retry": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/middleware-retry": { - "version": "3.229.0", - "license": "Apache-2.0", + "node_modules/@aws-sdk/types": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.398.0.tgz", + "integrity": "sha512-r44fkS+vsEgKCuEuTV+TIk0t0m5ZlXHNjSDYEUvzLStbbfUFiNus/YG4UCa0wOk9R7VuQI67badsvvPeVPCGDQ==", "optional": true, "dependencies": { - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/service-error-classification": "3.229.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/util-middleware": "3.226.0", - "tslib": "^2.3.1", - "uuid": "^8.3.2" + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/middleware-sdk-sts": { - "version": "3.226.0", - "license": "Apache-2.0", + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.398.0.tgz", + "integrity": "sha512-Fy0gLYAei/Rd6BrXG4baspCnWTUSd0NdokU1pZh4KlfEAEN1i8SPPgfiO5hLk7+2inqtCmqxVJlfqbMVe9k4bw==", "optional": true, "dependencies": { - "@aws-sdk/middleware-signing": "3.226.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/signature-v4": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/middleware-serde": { - "version": "3.226.0", - "license": "Apache-2.0", + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/middleware-signing": { - "version": "3.226.0", - "license": "Apache-2.0", + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.398.0.tgz", + "integrity": "sha512-A3Tzx1tkDHlBT+IgxmsMCHbV8LM7SwwCozq2ZjJRx0nqw3MCrrcxQFXldHeX/gdUMO+0Oocb7HGSnVODTq+0EA==", "optional": true, "dependencies": { - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/signature-v4": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/util-middleware": "3.226.0", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" + "@aws-sdk/types": "3.398.0", + "@smithy/types": "^2.2.2", + "bowser": "^2.11.0", + "tslib": "^2.5.0" } }, - "node_modules/@aws-sdk/middleware-stack": { - "version": "3.226.0", - "license": "Apache-2.0", + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.398.0.tgz", + "integrity": "sha512-RTVQofdj961ej4//fEkppFf4KXqKGMTCqJYghx3G0C/MYXbg7MGl7LjfNGtJcboRE8pfHHQ/TUWBDA7RIAPPlQ==", "optional": true, "dependencies": { - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/node-config-provider": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } } }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.226.0", - "license": "Apache-2.0", + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", "optional": true, "dependencies": { - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/types": "3.226.0", "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/node-config-provider": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "license": "MIT", "dependencies": { - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/shared-ini-file-loader": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@babel/highlight": "^7.18.6" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/node-http-handler": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-sdk/abort-controller": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/querystring-builder": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - }, + "node_modules/@babel/compat-data": { + "version": "7.20.5", + "license": "MIT", "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/property-provider": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/core": { + "version": "7.20.5", + "license": "MIT", "dependencies": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.0", + "@babel/helper-module-transforms": "^7.20.2", + "@babel/helpers": "^7.20.5", + "@babel/parser": "^7.20.5", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@aws-sdk/protocol-http": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.1", + "license": "MIT", "dependencies": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "ms": "2.1.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@aws-sdk/querystring-builder": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-sdk/types": "3.226.0", - "@aws-sdk/util-uri-escape": "3.201.0", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@aws-sdk/querystring-parser": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/generator": { + "version": "7.20.5", + "license": "MIT", "dependencies": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@babel/types": "^7.20.5", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/service-error-classification": { - "version": "3.229.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, "engines": { - "node": ">=14.0.0" + "node": ">=6.0.0" } }, - "node_modules/@aws-sdk/shared-ini-file-loader": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "dev": true, + "license": "MIT", "dependencies": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@babel/types": "^7.18.6" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/signature-v4": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.18.9", + "dev": true, + "license": "MIT", "dependencies": { - "@aws-sdk/is-array-buffer": "3.201.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/util-hex-encoding": "3.201.0", - "@aws-sdk/util-middleware": "3.226.0", - "@aws-sdk/util-uri-escape": "3.201.0", - "tslib": "^2.3.1" + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.9" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/smithy-client": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.20.0", + "license": "MIT", "dependencies": { - "@aws-sdk/middleware-stack": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@babel/compat-data": "^7.20.0", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.21.3", + "semver": "^6.3.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.229.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.20.5", + "dev": true, + "license": "MIT", "dependencies": { - "@aws-sdk/client-sso-oidc": "3.229.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/shared-ini-file-loader": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.19.1", + "@babel/helper-split-export-declaration": "^7.18.6" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@aws-sdk/types": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.20.5", + "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^2.3.1" + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.2.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@aws-sdk/url-parser": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.3", + "dev": true, + "license": "MIT", "dependencies": { - "@aws-sdk/querystring-parser": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" } }, - "node_modules/@aws-sdk/util-base64": { - "version": "3.208.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "license": "MIT", "dependencies": { - "@aws-sdk/util-buffer-from": "3.208.0", - "tslib": "^2.3.1" + "ms": "2.1.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@aws-sdk/util-body-length-browser": { - "version": "3.188.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "tslib": "^2.3.1" + "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@aws-sdk/util-body-length-node": { - "version": "3.208.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.18.6", + "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^2.3.1" + "@babel/types": "^7.18.6" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/util-buffer-from": { - "version": "3.208.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-function-name": { + "version": "7.19.0", + "license": "MIT", "dependencies": { - "@aws-sdk/is-array-buffer": "3.201.0", - "tslib": "^2.3.1" + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/util-config-provider": { - "version": "3.208.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "license": "MIT", "dependencies": { - "tslib": "^2.3.1" + "@babel/types": "^7.18.6" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/util-defaults-mode-browser": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "dev": true, + "license": "MIT", "dependencies": { - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/types": "3.226.0", - "bowser": "^2.11.0", - "tslib": "^2.3.1" + "@babel/types": "^7.18.9" }, "engines": { - "node": ">= 10.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/util-defaults-mode-node": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "license": "MIT", "dependencies": { - "@aws-sdk/config-resolver": "3.226.0", - "@aws-sdk/credential-provider-imds": "3.226.0", - "@aws-sdk/node-config-provider": "3.226.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@babel/types": "^7.18.6" }, "engines": { - "node": ">= 10.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-module-transforms": { + "version": "7.20.2", + "license": "MIT", "dependencies": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.20.1", + "@babel/types": "^7.20.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/util-hex-encoding": { - "version": "3.201.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^2.3.1" + "@babel/types": "^7.18.6" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/util-locate-window": { - "version": "3.208.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.20.2", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.18.9", + "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^2.3.1" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-wrap-function": "^7.18.9", + "@babel/types": "^7.18.9" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@aws-sdk/util-middleware": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-replace-supers": { + "version": "7.19.1", + "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^2.3.1" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.19.1", + "@babel/types": "^7.19.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/util-retry": { - "version": "3.229.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-simple-access": { + "version": "7.20.2", + "license": "MIT", "dependencies": { - "@aws-sdk/service-error-classification": "3.229.0", - "tslib": "^2.3.1" + "@babel/types": "^7.20.2" }, "engines": { - "node": ">= 14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/util-uri-escape": { - "version": "3.201.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.20.0", + "license": "MIT", "dependencies": { - "tslib": "^2.3.1" + "@babel/types": "^7.20.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-sdk/types": "3.226.0", - "bowser": "^2.11.0", - "tslib": "^2.3.1" - } - }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.226.0", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "license": "MIT", "dependencies": { - "@aws-sdk/node-config-provider": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@babel/types": "^7.18.6" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/util-utf8-browser": { - "version": "3.188.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "tslib": "^2.3.1" + "node_modules/@babel/helper-string-parser": { + "version": "7.19.4", + "license": "MIT", + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/util-utf8-node": { - "version": "3.208.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-sdk/util-buffer-from": "3.208.0", - "tslib": "^2.3.1" - }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "license": "MIT", "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame": { + "node_modules/@babel/helper-validator-option": { "version": "7.18.6", "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.18.6" - }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/compat-data": { + "node_modules/@babel/helper-wrap-function": { "version": "7.20.5", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-function-name": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5" + }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/core": { - "version": "7.20.5", + "node_modules/@babel/helpers": { + "version": "7.20.6", "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-module-transforms": "^7.20.2", - "@babel/helpers": "^7.20.5", - "@babel/parser": "^7.20.5", "@babel/template": "^7.18.10", "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" + "@babel/types": "^7.20.5" }, "engines": { "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/debug": { - "version": "4.3.1", + "node_modules/@babel/highlight": { + "version": "7.18.6", "license": "MIT", "dependencies": { - "ms": "2.1.2" + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node": ">=6.9.0" } }, - "node_modules/@babel/generator": { - "version": "7.20.5", + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", "license": "MIT", "dependencies": { - "@babel/types": "^7.20.5", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=4" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", + "node_modules/@babel/parser": { + "version": "7.20.5", "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "bin": { + "parser": "bin/babel-parser.js" }, "engines": { "node": ">=6.0.0" } }, - "node_modules/@babel/helper-annotate-as-pure": { + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.18.9", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-proposal-optional-chaining": "^7.18.9" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.0", + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.20.1", + "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.20.0", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "semver": "^6.3.0" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.20.5", + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-member-expression-to-functions": "^7.18.9", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.19.1", - "@babel/helper-split-export-declaration": "^7.18.6" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.20.5", + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.2.1" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.12.0" } }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.3.3", + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.4.0-0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { - "version": "4.3.4", + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { - "node": ">=6.0" + "node": ">=6.9.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { - "version": "6.3.0", + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.18.6", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-environment-visitor": { + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { "version": "7.18.9", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-explode-assignable-expression": { + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "license": "MIT", - "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { + "node_modules/@babel/plugin-proposal-numeric-separator": { "version": "7.18.6", + "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.18.9", + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.20.2", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.18.9" + "@babel/compat-data": "^7.20.1", + "@babel/helper-compilation-targets": "^7.20.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.20.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-module-imports": { + "node_modules/@babel/plugin-proposal-optional-catch-binding": { "version": "7.18.6", + "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.20.2", + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.18.9", "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.2" + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-optimise-call-expression": { + "node_modules/@babel/plugin-proposal-private-methods": { "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.18.9", + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.20.5", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" + "@babel/helper-create-class-features-plugin": "^7.20.5", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.19.1", + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.18.9", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/traverse": "^7.19.1", - "@babel/types": "^7.19.0" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.20.2" + "node": ">=4" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.20.0", + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.20.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.18.6", - "license": "MIT", - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.20.5", + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" + "@babel/helper-plugin-utils": "^7.12.13" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helpers": { - "version": "7.20.6", + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=4" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/parser": { - "version": "7.20.5", + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "dev": true, "license": "MIT", - "bin": { - "parser": "bin/babel-parser.js" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" }, - "engines": { - "node": ">=6.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.18.6", + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.20.0", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.19.0" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.18.9", + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", - "@babel/plugin-proposal-optional-chaining": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" + "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { - "@babel/core": "^7.13.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.20.1", + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-class-properties": { + "node_modules/@babel/plugin-syntax-jsx": { "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { @@ -1564,44 +1505,77 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.18.6", + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-class-static-block": "^7.14.5" + "@babel/helper-plugin-utils": "^7.10.4" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { - "@babel/core": "^7.12.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { "node": ">=6.9.0" @@ -1610,13 +1584,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.18.6", + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { "node": ">=6.9.0" @@ -1625,13 +1598,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.18.9", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.20.0", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + "@babel/helper-plugin-utils": "^7.19.0" }, "engines": { "node": ">=6.9.0" @@ -1640,13 +1612,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "node_modules/@babel/plugin-transform-arrow-functions": { "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1655,13 +1626,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-numeric-separator": { + "node_modules/@babel/plugin-transform-async-to-generator": { "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { + "@babel/helper-module-imports": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "@babel/helper-remap-async-to-generator": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1670,16 +1642,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.2", + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.20.1", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.1" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1688,13 +1656,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.20.5", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1703,13 +1670,20 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.18.9", + "node_modules/@babel/plugin-transform-classes": { + "version": "7.20.2", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-compilation-targets": "^7.20.0", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-replace-supers": "^7.19.1", + "@babel/helper-split-export-declaration": "^7.18.6", + "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" @@ -1718,13 +1692,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.18.6", + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.18.9", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -1733,15 +1706,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.20.5", + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.20.2", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.20.5", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1750,7 +1720,7 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "node_modules/@babel/plugin-transform-dotall-regex": { "version": "7.18.6", "dev": true, "license": "MIT", @@ -1759,51 +1729,63 @@ "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { - "node": ">=4" + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.18.9", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.18.8", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.18.9", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -1812,33 +1794,40 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", + "node_modules/@babel/plugin-transform-literals": { + "version": "7.18.9", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.20.0", + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.19.6", "dev": true, "license": "MIT", "dependencies": { + "@babel/helper-module-transforms": "^7.19.6", "@babel/helper-plugin-utils": "^7.19.0" }, "engines": { @@ -1848,33 +1837,45 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.19.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-module-transforms": "^7.19.6", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-simple-access": "^7.19.4" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.19.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.19.6", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-validator-identifier": "^7.19.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-jsx": { + "node_modules/@babel/plugin-transform-modules-umd": { "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { + "@babel/helper-module-transforms": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { @@ -1884,77 +1885,56 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.20.5", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-create-regexp-features-plugin": "^7.20.5", + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.20.5", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1963,12 +1943,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1977,12 +1957,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.20.0", + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.20.5", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-plugin-utils": "^7.20.2", + "regenerator-transform": "^0.15.1" }, "engines": { "node": ">=6.9.0" @@ -1991,7 +1972,7 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-arrow-functions": { + "node_modules/@babel/plugin-transform-reserved-words": { "version": "7.18.6", "dev": true, "license": "MIT", @@ -2005,14 +1986,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-async-to-generator": { + "node_modules/@babel/plugin-transform-shorthand-properties": { "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-remap-async-to-generator": "^7.18.6" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -2021,12 +2000,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", + "node_modules/@babel/plugin-transform-spread": { + "version": "7.19.0", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -2035,12 +2015,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.20.5", + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.18.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -2049,20 +2029,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.20.2", + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.18.9", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-replace-supers": "^7.19.1", - "@babel/helper-split-export-declaration": "^7.18.6", - "globals": "^11.1.0" + "@babel/helper-plugin-utils": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -2071,7 +2043,7 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-computed-properties": { + "node_modules/@babel/plugin-transform-typeof-symbol": { "version": "7.18.9", "dev": true, "license": "MIT", @@ -2085,12 +2057,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.20.2", + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.18.10", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -2099,7 +2071,7 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-dotall-regex": { + "node_modules/@babel/plugin-transform-unicode-regex": { "version": "7.18.6", "dev": true, "license": "MIT", @@ -2114,12 +2086,86 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.18.9", + "node_modules/@babel/preset-env": { + "version": "7.20.2", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/compat-data": "^7.20.1", + "@babel/helper-compilation-targets": "^7.20.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-async-generator-functions": "^7.20.1", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.20.2", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.20.0", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.20.2", + "@babel/plugin-transform-classes": "^7.20.2", + "@babel/plugin-transform-computed-properties": "^7.18.9", + "@babel/plugin-transform-destructuring": "^7.20.2", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.9", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-function-name": "^7.18.9", + "@babel/plugin-transform-literals": "^7.18.9", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.19.6", + "@babel/plugin-transform-modules-commonjs": "^7.19.6", + "@babel/plugin-transform-modules-systemjs": "^7.19.6", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.20.1", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.19.0", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.9", + "@babel/plugin-transform-typeof-symbol": "^7.18.9", + "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-regex": "^7.18.6", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.20.2", + "babel-plugin-polyfill-corejs2": "^0.3.3", + "babel-plugin-polyfill-corejs3": "^0.6.0", + "babel-plugin-polyfill-regenerator": "^0.4.1", + "core-js-compat": "^3.25.1", + "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" @@ -2128,1061 +2174,1153 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.18.8", + "node_modules/@babel/preset-modules": { + "version": "0.1.5", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.18.9", + "node_modules/@babel/runtime": { + "version": "7.20.6", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9" + "regenerator-runtime": "^0.13.11" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.18.9", - "dev": true, + "node_modules/@babel/template": { + "version": "7.18.10", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "dev": true, + "node_modules/@babel/traverse": { + "version": "7.20.5", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.20.5", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.20.5", + "@babel/types": "^7.20.5", + "debug": "^4.1.0", + "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.19.6", - "dev": true, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.1", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helper-plugin-utils": "^7.19.0" + "ms": "2.1.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.19.6", - "dev": true, + "node_modules/@babel/types": { + "version": "7.20.5", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-simple-access": "^7.19.4" + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", + "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.19.6", + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc": { + "version": "1.3.3", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-validator-identifier": "^7.19.1" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.18.6", + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.4", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "ms": "2.1.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.20.5", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.19.0", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.20.5", - "@babel/helper-plugin-utils": "^7.20.2" + "type-fest": "^0.20.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=8" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.18.6", + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "argparse": "^2.0.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.18.6", + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.7", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=10.10.0" } }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.20.5", + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.3.4", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "ms": "2.1.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.18.6", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": ">=12.22" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.20.5", + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "dev": true, + "license": "ISC", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "regenerator-transform": "^0.15.1" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.18.6", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", + "node_modules/@jest/console": { + "version": "29.3.1", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@jest/types": "^29.3.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.19.0", + "node_modules/@jest/core": { + "version": "29.3.1", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" + "@jest/console": "^29.3.1", + "@jest/reporters": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.2.0", + "jest-config": "^29.3.1", + "jest-haste-map": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-regex-util": "^29.2.0", + "jest-resolve": "^29.3.1", + "jest-resolve-dependencies": "^29.3.1", + "jest-runner": "^29.3.1", + "jest-runtime": "^29.3.1", + "jest-snapshot": "^29.3.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", + "jest-watcher": "^29.3.1", + "micromatch": "^4.0.4", + "pretty-format": "^29.3.1", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=6.9.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", + "node_modules/@jest/environment": { + "version": "29.3.1", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@jest/fake-timers": "^29.3.1", + "@jest/types": "^29.3.1", + "@types/node": "*", + "jest-mock": "^29.3.1" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.18.9", + "node_modules/@jest/expect": { + "version": "29.3.1", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "expect": "^29.3.1", + "jest-snapshot": "^29.3.1" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.18.9", - "dev": true, - "license": "MIT", + "node_modules/@jest/expect-utils": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", + "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "jest-get-type": "^29.4.3" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", + "node_modules/@jest/fake-timers": { + "version": "29.3.1", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@jest/types": "^29.3.1", + "@sinonjs/fake-timers": "^9.1.2", + "@types/node": "*", + "jest-message-util": "^29.3.1", + "jest-mock": "^29.3.1", + "jest-util": "^29.3.1" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", + "node_modules/@jest/globals": { + "version": "29.3.1", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@jest/environment": "^29.3.1", + "@jest/expect": "^29.3.1", + "@jest/types": "^29.3.1", + "jest-mock": "^29.3.1" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@babel/preset-env": { - "version": "7.20.2", + "node_modules/@jest/reporters": { + "version": "29.3.1", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.20.1", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-async-generator-functions": "^7.20.1", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.18.6", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.20.2", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.20.0", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.18.6", - "@babel/plugin-transform-async-to-generator": "^7.18.6", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.20.2", - "@babel/plugin-transform-classes": "^7.20.2", - "@babel/plugin-transform-computed-properties": "^7.18.9", - "@babel/plugin-transform-destructuring": "^7.20.2", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.9", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.18.8", - "@babel/plugin-transform-function-name": "^7.18.9", - "@babel/plugin-transform-literals": "^7.18.9", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.19.6", - "@babel/plugin-transform-modules-commonjs": "^7.19.6", - "@babel/plugin-transform-modules-systemjs": "^7.19.6", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.20.1", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.18.6", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.19.0", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.9", - "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.20.2", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "core-js-compat": "^3.25.1", - "semver": "^6.3.0" + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", + "@jridgewell/trace-mapping": "^0.3.15", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1", + "jest-worker": "^29.3.1", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" }, "engines": { - "node": ">=6.9.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@jest/schemas": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", + "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "dependencies": { + "@sinclair/typebox": "^0.25.16" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@babel/preset-modules": { - "version": "0.1.5", + "node_modules/@jest/source-map": { + "version": "29.2.0", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" + "@jridgewell/trace-mapping": "^0.3.15", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@babel/runtime": { - "version": "7.20.6", + "node_modules/@jest/test-result": { + "version": "29.3.1", "dev": true, "license": "MIT", "dependencies": { - "regenerator-runtime": "^0.13.11" + "@jest/console": "^29.3.1", + "@jest/types": "^29.3.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": ">=6.9.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@babel/template": { - "version": "7.18.10", + "node_modules/@jest/test-sequencer": { + "version": "29.3.1", + "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@jest/test-result": "^29.3.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.3.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=6.9.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@babel/traverse": { - "version": "7.20.5", + "node_modules/@jest/transform": { + "version": "29.3.1", + "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.5", - "@babel/types": "^7.20.5", - "debug": "^4.1.0", - "globals": "^11.1.0" + "@babel/core": "^7.11.6", + "@jest/types": "^29.3.1", + "@jridgewell/trace-mapping": "^0.3.15", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.3.1", + "jest-regex-util": "^29.2.0", + "jest-util": "^29.3.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.1" }, "engines": { - "node": ">=6.9.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.3.1", - "license": "MIT", + "node_modules/@jest/transform/node_modules/convert-source-map": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/types": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", + "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", "dependencies": { - "ms": "2.1.2" + "@jest/schemas": "^29.4.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@babel/types": { - "version": "7.20.5", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0.0" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "dev": true, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", "license": "MIT" }, - "node_modules/@eslint/eslintrc": { - "version": "1.3.3", - "dev": true, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", "license": "MIT", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.10", + "license": "BSD-3-Clause", + "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" }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", + "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + } }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.4", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 8" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.19.0", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", "dev": true, "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 8" } }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">= 8" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.7", + "node_modules/@sinclair/typebox": { + "version": "0.25.24", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", + "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==" + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.6", "dev": true, - "license": "Apache-2.0", + "license": "BSD-3-Clause", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" + "type-detect": "4.0.8" } }, - "node_modules/@humanwhocodes/config-array/node_modules/debug": { - "version": "4.3.4", + "node_modules/@sinonjs/fake-timers": { + "version": "9.1.2", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "ms": "2.1.2" + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.5.tgz", + "integrity": "sha512-byVZ2KWLMPYAZGKjRpniAzLcygJO4ruClZKdJTuB0eCB76ONFTdptBHlviHpAZXknRz7skYWPfcgO9v30A1SyA==", + "optional": true, + "dependencies": { + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=14.0.0" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "dev": true, - "license": "Apache-2.0", + "node_modules/@smithy/config-resolver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.5.tgz", + "integrity": "sha512-n0c2AXz+kjALY2FQr7Zy9zhYigXzboIh1AuUUVCqFBKFtdEvTwnwPXrTDoEehLiRTUHNL+4yzZ3s+D0kKYSLSg==", + "optional": true, + "dependencies": { + "@smithy/types": "^2.2.2", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.0", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=12.22" + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.5.tgz", + "integrity": "sha512-KFcf/e0meFkQNyteJ65f1G19sgUEY1e5zL7hyAEUPz2SEfBmC9B37WyRq87G3MEEsvmAWwCRu7nFFYUKtR3svQ==", + "optional": true, + "dependencies": { + "@smithy/node-config-provider": "^2.0.5", + "@smithy/property-provider": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/url-parser": "^2.0.5", + "tslib": "^2.5.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.5.tgz", + "integrity": "sha512-iqR6OuOV3zbQK8uVs9o+9AxhVk8kW9NAxA71nugwUB+kTY9C35pUd0A5/m4PRT0Y0oIW7W4kgnSR3fdYXQjECw==", + "optional": true, + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.2.2", + "@smithy/util-hex-encoding": "^2.0.0", + "tslib": "^2.5.0" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "dev": true, - "license": "BSD-3-Clause" + "node_modules/@smithy/fetch-http-handler": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.0.5.tgz", + "integrity": "sha512-EzFoMowdBNy1VqtvkiXgPFEdosIAt4/4bgZ8uiDiUyfhmNXq/3bV+CagPFFBsgFOR/X2XK4zFZHRsoa7PNHVVg==", + "optional": true, + "dependencies": { + "@smithy/protocol-http": "^2.0.5", + "@smithy/querystring-builder": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/util-base64": "^2.0.0", + "tslib": "^2.5.0" + } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "dev": true, - "license": "ISC", + "node_modules/@smithy/hash-node": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.5.tgz", + "integrity": "sha512-mk551hIywBITT+kXruRNXk7f8Fy7DTzBjZJSr/V6nolYKmUHIG3w5QU6nO9qPYEQGKc/yEPtkpdS28ndeG93lA==", + "optional": true, "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "@smithy/types": "^2.2.2", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "node_modules/@smithy/invalid-dependency": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.5.tgz", + "integrity": "sha512-0wEi+JT0hM+UUwrJVYbqjuGFhy5agY/zXyiN7BNAJ1XoCDjU5uaNSj8ekPWsXd/d4yM6NSe8UbPd8cOc1+3oBQ==", + "optional": true, + "dependencies": { + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "node_modules/@jest/console": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "node_modules/@smithy/is-array-buffer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", + "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", + "optional": true, "dependencies": { - "@jest/types": "^29.3.1", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1", - "slash": "^3.0.0" + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jest/core": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "node_modules/@smithy/middleware-content-length": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.5.tgz", + "integrity": "sha512-E7VwV5H02fgZIUGRli4GevBCAPvkyEI/fgl9SU47nPPi3DAAX3nEtUb8xfGbXjOcJ5BdSUoWWZn42tEd/blOqA==", + "optional": true, "dependencies": { - "@jest/console": "^29.3.1", - "@jest/reporters": "^29.3.1", - "@jest/test-result": "^29.3.1", - "@jest/transform": "^29.3.1", - "@jest/types": "^29.3.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.2.0", - "jest-config": "^29.3.1", - "jest-haste-map": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-regex-util": "^29.2.0", - "jest-resolve": "^29.3.1", - "jest-resolve-dependencies": "^29.3.1", - "jest-runner": "^29.3.1", - "jest-runtime": "^29.3.1", - "jest-snapshot": "^29.3.1", - "jest-util": "^29.3.1", - "jest-validate": "^29.3.1", - "jest-watcher": "^29.3.1", - "micromatch": "^4.0.4", - "pretty-format": "^29.3.1", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" + "@smithy/protocol-http": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=14.0.0" } }, - "node_modules/@jest/environment": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "node_modules/@smithy/middleware-endpoint": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.0.5.tgz", + "integrity": "sha512-tyzDuoNTbsMQCq5Xkc4QOt6e2GACUllQIV8SQ5fc59FtOIV9/vbf58/GxVjZm2o8+MMbdDBANjTDZe/ijZKfyA==", + "optional": true, "dependencies": { - "@jest/fake-timers": "^29.3.1", - "@jest/types": "^29.3.1", - "@types/node": "*", - "jest-mock": "^29.3.1" + "@smithy/middleware-serde": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/url-parser": "^2.0.5", + "@smithy/util-middleware": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jest/expect": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "node_modules/@smithy/middleware-retry": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.5.tgz", + "integrity": "sha512-ulIfbFyzQTVnJbLjUl1CTSi0etg6tej/ekwaLp0Gn8ybUkDkKYa+uB6CF/m2J5B6meRwyJlsryR+DjaOVyiicg==", + "optional": true, "dependencies": { - "expect": "^29.3.1", - "jest-snapshot": "^29.3.1" + "@smithy/protocol-http": "^2.0.5", + "@smithy/service-error-classification": "^2.0.0", + "@smithy/types": "^2.2.2", + "@smithy/util-middleware": "^2.0.0", + "@smithy/util-retry": "^2.0.0", + "tslib": "^2.5.0", + "uuid": "^8.3.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", + "node_modules/@smithy/middleware-serde": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.5.tgz", + "integrity": "sha512-in0AA5sous74dOfTGU9rMJBXJ0bDVNxwdXtEt5lh3FVd2sEyjhI+rqpLLRF1E4ixbw3RSEf80hfRpcPdjg4vvQ==", + "optional": true, "dependencies": { - "jest-get-type": "^29.4.3" + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jest/fake-timers": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "node_modules/@smithy/middleware-stack": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.0.tgz", + "integrity": "sha512-31XC1xNF65nlbc16yuh3wwTudmqs6qy4EseQUGF8A/p2m/5wdd/cnXJqpniy/XvXVwkHPz/GwV36HqzHtIKATQ==", + "optional": true, "dependencies": { - "@jest/types": "^29.3.1", - "@sinonjs/fake-timers": "^9.1.2", - "@types/node": "*", - "jest-message-util": "^29.3.1", - "jest-mock": "^29.3.1", - "jest-util": "^29.3.1" + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jest/globals": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "node_modules/@smithy/node-config-provider": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.0.5.tgz", + "integrity": "sha512-LRtjV9WkhONe2lVy+ipB/l1GX60ybzBmFyeRUoLUXWKdnZ3o81jsnbKzMK8hKq8eFSWPk+Lmyx6ZzCQabGeLxg==", + "optional": true, "dependencies": { - "@jest/environment": "^29.3.1", - "@jest/expect": "^29.3.1", - "@jest/types": "^29.3.1", - "jest-mock": "^29.3.1" + "@smithy/property-provider": "^2.0.5", + "@smithy/shared-ini-file-loader": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jest/reporters": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "node_modules/@smithy/node-http-handler": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.0.5.tgz", + "integrity": "sha512-lZm5DZf4b3V0saUw9WTC4/du887P6cy2fUyQgQQKRRV6OseButyD5yTzeMmXE53CaXJBMBsUvvIQ0hRVxIq56w==", + "optional": true, "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.3.1", - "@jest/test-result": "^29.3.1", - "@jest/transform": "^29.3.1", - "@jest/types": "^29.3.1", - "@jridgewell/trace-mapping": "^0.3.15", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1", - "jest-worker": "^29.3.1", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" + "@smithy/abort-controller": "^2.0.5", + "@smithy/protocol-http": "^2.0.5", + "@smithy/querystring-builder": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=14.0.0" } }, - "node_modules/@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "node_modules/@smithy/property-provider": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.5.tgz", + "integrity": "sha512-cAFSUhX6aiHcmpWfrCLKvwBtgN1F6A0N8qY/8yeSi0LRLmhGqsY1/YTxFE185MCVzYbqBGXVr9TBv4RUcIV4rA==", + "optional": true, "dependencies": { - "@sinclair/typebox": "^0.25.16" + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jest/source-map": { - "version": "29.2.0", - "dev": true, - "license": "MIT", + "node_modules/@smithy/protocol-http": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-2.0.5.tgz", + "integrity": "sha512-d2hhHj34mA2V86doiDfrsy2fNTnUOowGaf9hKb0hIPHqvcnShU4/OSc4Uf1FwHkAdYF3cFXTrj5VGUYbEuvMdw==", + "optional": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.15", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jest/test-result": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "node_modules/@smithy/querystring-builder": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.5.tgz", + "integrity": "sha512-4DCX9krxLzATj+HdFPC3i8pb7XTAWzzKqSw8aTZMjXjtQY+vhe4azMAqIvbb6g7JKwIkmkRAjK6EXO3YWSnJVQ==", + "optional": true, "dependencies": { - "@jest/console": "^29.3.1", - "@jest/types": "^29.3.1", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "@smithy/types": "^2.2.2", + "@smithy/util-uri-escape": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jest/test-sequencer": { - "version": "29.3.1", - "dev": true, - "license": "MIT", + "node_modules/@smithy/querystring-parser": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.5.tgz", + "integrity": "sha512-C2stCULH0r54KBksv3AWcN8CLS3u9+WsEW8nBrvctrJ5rQTNa1waHkffpVaiKvcW2nP0aIMBPCobD/kYf/q9mA==", + "optional": true, "dependencies": { - "@jest/test-result": "^29.3.1", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.3.1", - "slash": "^3.0.0" + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jest/transform": { - "version": "29.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.3.1", - "@jridgewell/trace-mapping": "^0.3.15", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.3.1", - "jest-regex-util": "^29.2.0", - "jest-util": "^29.3.1", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.1" + "node_modules/@smithy/service-error-classification": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.0.tgz", + "integrity": "sha512-2z5Nafy1O0cTf69wKyNjGW/sNVMiqDnb4jgwfMG8ye8KnFJ5qmJpDccwIbJNhXIfbsxTg9SEec2oe1cexhMJvw==", + "optional": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.0.5.tgz", + "integrity": "sha512-Mvtk6FwMtfbKRC4YuSsIqRYp9WTxsSUJVVo2djgyhcacKGMqicHDWSAmgy3sDrKv+G/G6xTZCPwm6pJARtdxVg==", + "optional": true, + "dependencies": { + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jest/transform/node_modules/convert-source-map": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "node_modules/@smithy/signature-v4": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.5.tgz", + "integrity": "sha512-ABIzXmUDXK4n2c9cXjQLELgH2RdtABpYKT+U131e2I6RbCypFZmxIHmIBufJzU2kdMCQ3+thBGDWorAITFW04A==", + "optional": true, "dependencies": { - "@jest/schemas": "^29.4.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "@smithy/eventstream-codec": "^2.0.5", + "@smithy/is-array-buffer": "^2.0.0", + "@smithy/types": "^2.2.2", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-middleware": "^2.0.0", + "@smithy/util-uri-escape": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "license": "MIT", + "node_modules/@smithy/smithy-client": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.0.5.tgz", + "integrity": "sha512-kCTFr8wfOAWKDzGvfBElc6shHigWtHNhMQ1IbosjC4jOlayFyZMSs2PysKB+Ox/dhQ41KqOzgVjgiQ+PyWqHMQ==", + "optional": true, "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@smithy/middleware-stack": "^2.0.0", + "@smithy/types": "^2.2.2", + "@smithy/util-stream": "^2.0.5", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "license": "MIT", + "node_modules/@smithy/types": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.2.2.tgz", + "integrity": "sha512-4PS0y1VxDnELGHGgBWlDksB2LJK8TG8lcvlWxIsgR+8vROI7Ms8h1P4FQUx+ftAX2QZv5g1CJCdhdRmQKyonyw==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "license": "MIT", - "engines": { - "node": ">=6.0.0" + "node_modules/@smithy/url-parser": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.5.tgz", + "integrity": "sha512-OdMBvZhpckQSkugCXNJQCvqJ71wE7Ftxce92UOQLQ9pwF6hoS5PLL7wEfpnuEXtStzBqJYkzu1C1ZfjuFGOXAA==", + "optional": true, + "dependencies": { + "@smithy/querystring-parser": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "license": "MIT" + "node_modules/@smithy/util-base64": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.0.tgz", + "integrity": "sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==", + "optional": true, + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "license": "MIT", + "node_modules/@smithy/util-body-length-browser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", + "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", + "optional": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "tslib": "^2.5.0" } }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.10", - "license": "BSD-3-Clause", + "node_modules/@smithy/util-body-length-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", + "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", + "optional": true, "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" + "tslib": "^2.5.0" }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { - "version": "7.3.8", - "license": "ISC", + "node_modules/@smithy/util-buffer-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", + "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "optional": true, "dependencies": { - "lru-cache": "^6.0.0" + "@smithy/is-array-buffer": "^2.0.0", + "tslib": "^2.5.0" }, - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", + "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" }, "engines": { - "node": ">=10" + "node": ">=14.0.0" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, - "license": "MIT", + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.5.tgz", + "integrity": "sha512-yciP6TPttLsj731aHTvekgyuCGXQrEAJibEwEWAh3kzaDsfGAVCuZSBlyvC2Dl3TZmHKCOQwHV8mIE7KQCTPuQ==", + "optional": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@smithy/property-provider": "^2.0.5", + "@smithy/types": "^2.2.2", + "bowser": "^2.11.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">= 8" + "node": ">= 10.0.0" } }, - "node_modules/@nodelib/fs.stat": { + "node_modules/@smithy/util-defaults-mode-node": { "version": "2.0.5", - "dev": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.5.tgz", + "integrity": "sha512-M07t99rWasXt+IaDZDyP3BkcoEm/mgIE1RIMASrE49LKSNxaVN7PVcgGc77+4uu2kzBAyqJKy79pgtezuknyjQ==", + "optional": true, + "dependencies": { + "@smithy/config-resolver": "^2.0.5", + "@smithy/credential-provider-imds": "^2.0.5", + "@smithy/node-config-provider": "^2.0.5", + "@smithy/property-provider": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" + }, "engines": { - "node": ">= 8" + "node": ">= 10.0.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "license": "MIT", + "node_modules/@smithy/util-hex-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", + "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "optional": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "tslib": "^2.5.0" }, "engines": { - "node": ">= 8" + "node": ">=14.0.0" } }, - "node_modules/@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==" + "node_modules/@smithy/util-middleware": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.0.tgz", + "integrity": "sha512-eCWX4ECuDHn1wuyyDdGdUWnT4OGyIzV0LN1xRttBFMPI9Ff/4heSHVxneyiMtOB//zpXWCha1/SWHJOZstG7kA==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } }, - "node_modules/@sinonjs/commons": { - "version": "1.8.6", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/@smithy/util-retry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.0.tgz", + "integrity": "sha512-/dvJ8afrElasuiiIttRJeoS2sy8YXpksQwiM/TcepqdRVp7u4ejd9C4IQURHNjlfPUT7Y6lCDSa2zQJbdHhVTg==", + "optional": true, "dependencies": { - "type-detect": "4.0.8" + "@smithy/service-error-classification": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 14.0.0" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "9.1.2", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/@smithy/util-stream": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.5.tgz", + "integrity": "sha512-ylx27GwI05xLpYQ4hDIfS15vm+wYjNN0Sc2P0FxuzgRe8v0BOLHppGIQ+Bezcynk8C9nUzsUue3TmtRhjut43g==", + "optional": true, "dependencies": { - "@sinonjs/commons": "^1.7.0" + "@smithy/fetch-http-handler": "^2.0.5", + "@smithy/node-http-handler": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "license": "MIT", + "node_modules/@smithy/util-uri-escape": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", + "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, "engines": { - "node": ">= 6" + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", + "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", + "optional": true, + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, "node_modules/@types/babel__core": { @@ -3273,11 +3411,13 @@ }, "node_modules/@types/webidl-conversions": { "version": "7.0.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" }, "node_modules/@types/whatwg-url": { "version": "8.2.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", "dependencies": { "@types/node": "*", "@types/webidl-conversions": "*" @@ -3311,7 +3451,7 @@ }, "node_modules/acorn": { "version": "8.8.1", - "devOptional": true, + "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -3328,14 +3468,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/agent-base": { "version": "6.0.2", "license": "MIT", @@ -3478,17 +3610,6 @@ "dev": true, "license": "MIT" }, - "node_modules/ast-types": { - "version": "0.13.4", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/asynckit": { "version": "0.4.0", "dev": true, @@ -3566,9 +3687,10 @@ } }, "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.0", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -3651,6 +3773,8 @@ }, "node_modules/base64-js": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "funding": [ { "type": "github", @@ -3664,8 +3788,7 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/base64url": { "version": "3.0.1", @@ -3761,7 +3884,8 @@ }, "node_modules/bowser": { "version": "2.11.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", "optional": true }, "node_modules/brace-expansion": { @@ -3825,6 +3949,8 @@ }, "node_modules/buffer": { "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "funding": [ { "type": "github", @@ -3839,7 +3965,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -3897,7 +4022,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001439", + "version": "1.0.30001524", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001524.tgz", + "integrity": "sha512-Jj917pJtYg9HSJBF95HVX3Cdr89JUyLT4IZ8SvM5aDRni95swKgYi3TgYLH5hnGfPE/U1dg6IfZ50UsIlLkwSA==", "funding": [ { "type": "opencollective", @@ -3906,9 +4033,12 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } - ], - "license": "CC-BY-4.0" + ] }, "node_modules/chalk": { "version": "4.1.0", @@ -4089,24 +4219,23 @@ } }, "node_modules/cloudinary": { - "version": "1.32.0", - "license": "MIT", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-1.40.0.tgz", + "integrity": "sha512-Fifkl8NRw/M+Enw4cKCXc6e0Or28c5y6RVGYS3OCLzT1W8EfBt416FURhLuuL/S4BCVv8bSilmnM746kCtth3g==", "dependencies": { - "cloudinary-core": "^2.10.2", - "core-js": "^3.6.5", + "cloudinary-core": "^2.13.0", + "core-js": "^3.30.1", "lodash": "^4.17.21", "q": "^1.5.1" }, "engines": { "node": ">=0.6" - }, - "optionalDependencies": { - "proxy-agent": "^5.0.0" } }, "node_modules/cloudinary-core": { - "version": "2.11.3", - "license": "MIT", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/cloudinary-core/-/cloudinary-core-2.13.0.tgz", + "integrity": "sha512-Nt0Q5I2FtenmJghtC4YZ3MZZbGg1wLm84SsxcuVwZ83OyJqG9CNIGp86CiI6iDv3QobaqBUpOT7vg+HqY5HxEA==", "peerDependencies": { "lodash": ">=4.0" } @@ -4243,14 +4372,16 @@ "license": "MIT" }, "node_modules/cookiejar": { - "version": "2.1.3", - "dev": true, - "license": "MIT" + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true }, "node_modules/core-js": { - "version": "3.6.5", + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.32.1.tgz", + "integrity": "sha512-lqufgNn9NLnESg5mQeYsxQP5w7wrViSj0jr/kv6ECQiByzQkrn1MKvV0L3acttpDqfQrHLwr2KCMgX5b8X+lyQ==", "hasInstallScript": true, - "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/core-js" @@ -4309,14 +4440,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/data-uri-to-buffer": { - "version": "3.0.1", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/debug": { "version": "3.2.7", "dev": true, @@ -4332,7 +4455,7 @@ }, "node_modules/deep-is": { "version": "0.1.3", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/deepmerge": { @@ -4343,20 +4466,6 @@ "node": ">=0.10.0" } }, - "node_modules/degenerator": { - "version": "3.0.2", - "license": "MIT", - "optional": true, - "dependencies": { - "ast-types": "^0.13.2", - "escodegen": "^1.8.1", - "esprima": "^4.0.0", - "vm2": "^3.9.8" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "dev": true, @@ -4557,47 +4666,18 @@ "version": "3.1.1", "license": "MIT", "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "1.14.3", - "license": "BSD-2-Clause", - "optional": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=4.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" + "node": ">=6" } }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "4.3.0", - "license": "BSD-2-Clause", - "optional": true, + "node_modules/escape-html": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">=0.8.0" } }, "node_modules/eslint": { @@ -4856,7 +4936,7 @@ }, "node_modules/esprima": { "version": "4.0.1", - "devOptional": true, + "dev": true, "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", @@ -4898,7 +4978,7 @@ }, "node_modules/esutils": { "version": "2.0.3", - "devOptional": true, + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" @@ -5150,7 +5230,7 @@ }, "node_modules/fast-levenshtein": { "version": "2.0.6", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/fast-safe-stringify": { @@ -5159,18 +5239,25 @@ "license": "MIT" }, "node_modules/fast-xml-parser": { - "version": "4.0.11", - "license": "MIT", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], "optional": true, "dependencies": { "strnum": "^1.0.5" }, "bin": { "fxparser": "src/cli/cli.js" - }, - "funding": { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" } }, "node_modules/fastq": { @@ -5200,14 +5287,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/file-uri-to-path": { - "version": "2.0.0", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/fill-range": { "version": "7.0.1", "license": "MIT", @@ -5325,19 +5404,6 @@ "node": ">= 0.6" } }, - "node_modules/fs-extra": { - "version": "8.1.0", - "license": "MIT", - "optional": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, "node_modules/fs-minipass": { "version": "2.1.0", "license": "ISC", @@ -5362,38 +5428,6 @@ "version": "1.0.0", "license": "ISC" }, - "node_modules/ftp": { - "version": "0.3.10", - "optional": true, - "dependencies": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/ftp/node_modules/isarray": { - "version": "0.0.1", - "license": "MIT", - "optional": true - }, - "node_modules/ftp/node_modules/readable-stream": { - "version": "1.1.14", - "license": "MIT", - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ftp/node_modules/string_decoder": { - "version": "0.10.31", - "license": "MIT", - "optional": true - }, "node_modules/function-bind": { "version": "1.1.1", "license": "MIT" @@ -5473,38 +5507,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-uri": { - "version": "3.0.2", - "license": "MIT", - "optional": true, - "dependencies": { - "@tootallnate/once": "1", - "data-uri-to-buffer": "3", - "debug": "4", - "file-uri-to-path": "2", - "fs-extra": "^8.1.0", - "ftp": "^0.3.10" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/get-uri/node_modules/debug": { - "version": "4.3.4", - "license": "MIT", - "optional": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/glob": { "version": "7.1.6", "license": "ISC", @@ -5651,35 +5653,6 @@ "node": ">= 0.8" } }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "license": "MIT", - "optional": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "license": "MIT", - "optional": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/http-status-codes": { "version": "2.2.0", "license": "MIT" @@ -5730,6 +5703,8 @@ }, "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", @@ -5743,8 +5718,7 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "BSD-3-Clause" + ] }, "node_modules/ignore": { "version": "5.2.1", @@ -5821,9 +5795,9 @@ "license": "ISC" }, "node_modules/ip": { - "version": "1.1.8", - "license": "MIT", - "optional": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" }, "node_modules/ipaddr.js": { "version": "1.9.1", @@ -5952,9 +5926,10 @@ } }, "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -6474,9 +6449,10 @@ } }, "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.3.8", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, - "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -6635,8 +6611,9 @@ "license": "MIT" }, "node_modules/json5": { - "version": "2.2.1", - "license": "MIT", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "bin": { "json5": "lib/cli.js" }, @@ -6644,14 +6621,6 @@ "node": ">=6" } }, - "node_modules/jsonfile": { - "version": "4.0.0", - "license": "MIT", - "optional": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/jsonwebtoken": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", @@ -6668,9 +6637,9 @@ } }, "node_modules/jsonwebtoken/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -6699,8 +6668,9 @@ } }, "node_modules/kareem": { - "version": "2.5.0", - "license": "Apache-2.0", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", "engines": { "node": ">=12.0.0" } @@ -6806,8 +6776,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "license": "ISC", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -6988,7 +6959,8 @@ }, "node_modules/mongodb-connection-string-url": { "version": "2.6.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", "dependencies": { "@types/whatwg-url": "^8.2.1", "whatwg-url": "^11.0.0" @@ -6996,7 +6968,8 @@ }, "node_modules/mongodb-connection-string-url/node_modules/tr46": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", "dependencies": { "punycode": "^2.1.1" }, @@ -7006,14 +6979,16 @@ }, "node_modules/mongodb-connection-string-url/node_modules/webidl-conversions": { "version": "7.0.0", - "license": "BSD-2-Clause", + "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/mongodb-connection-string-url/node_modules/whatwg-url": { "version": "11.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "dependencies": { "tr46": "^3.0.0", "webidl-conversions": "^7.0.0" @@ -7023,12 +6998,13 @@ } }, "node_modules/mongoose": { - "version": "6.8.0", - "license": "MIT", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.12.0.tgz", + "integrity": "sha512-sd/q83C6TBRPBrrD2A/POSbA/exbCFM2WOuY7Lf2JuIJFlHFG39zYSDTTAEiYlzIfahNOLmXPxBGFxdAch41Mw==", "dependencies": { - "bson": "^4.7.0", - "kareem": "2.5.0", - "mongodb": "4.12.1", + "bson": "^4.7.2", + "kareem": "2.5.1", + "mongodb": "4.17.1", "mpath": "0.9.0", "mquery": "4.0.3", "ms": "2.1.3", @@ -7053,8 +7029,9 @@ } }, "node_modules/mongoose/node_modules/bson": { - "version": "4.7.0", - "license": "Apache-2.0", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz", + "integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==", "dependencies": { "buffer": "^5.6.0" }, @@ -7063,11 +7040,12 @@ } }, "node_modules/mongoose/node_modules/mongodb": { - "version": "4.12.1", - "license": "Apache-2.0", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.17.1.tgz", + "integrity": "sha512-MBuyYiPUPRTqfH2dV0ya4dcr2E5N52ocBuZ8Sgg/M030nGF78v855B3Z27mZJnp8PxjnUquEnAtjOsphgMZOlQ==", "dependencies": { - "bson": "^4.7.0", - "mongodb-connection-string-url": "^2.5.4", + "bson": "^4.7.2", + "mongodb-connection-string-url": "^2.6.0", "socks": "^2.7.1" }, "engines": { @@ -7075,7 +7053,7 @@ }, "optionalDependencies": { "@aws-sdk/credential-providers": "^3.186.0", - "saslprep": "^1.0.3" + "@mongodb-js/saslprep": "^1.1.0" } }, "node_modules/mongoose/node_modules/ms": { @@ -7175,14 +7153,6 @@ "version": "2.6.2", "license": "MIT" }, - "node_modules/netmask": { - "version": "2.0.2", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/node-addon-api": { "version": "5.0.0", "license": "MIT" @@ -7229,9 +7199,10 @@ } }, "node_modules/nodemon": { - "version": "2.0.20", + "version": "2.0.22", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", + "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", "dev": true, - "license": "MIT", "dependencies": { "chokidar": "^3.5.2", "debug": "^3.2.7", @@ -7406,52 +7377,6 @@ "node": ">=4" } }, - "node_modules/optionator": { - "version": "0.8.3", - "license": "MIT", - "optional": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/optionator/node_modules/levn": { - "version": "0.3.0", - "license": "MIT", - "optional": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/optionator/node_modules/prelude-ls": { - "version": "1.1.2", - "optional": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/optionator/node_modules/type-check": { - "version": "0.3.2", - "license": "MIT", - "optional": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/p-limit": { "version": "3.1.0", "dev": true, @@ -7499,54 +7424,6 @@ "node": ">=6" } }, - "node_modules/pac-proxy-agent": { - "version": "5.0.0", - "license": "MIT", - "optional": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4", - "get-uri": "3", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "5", - "pac-resolver": "^5.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "5" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/pac-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "license": "MIT", - "optional": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/pac-resolver": { - "version": "5.0.1", - "license": "MIT", - "optional": true, - "dependencies": { - "degenerator": "^3.0.2", - "ip": "^1.1.5", - "netmask": "^2.0.2" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/parent-module": { "version": "1.0.1", "dev": true, @@ -7739,58 +7616,6 @@ "node": ">= 0.10" } }, - "node_modules/proxy-agent": { - "version": "5.0.0", - "license": "MIT", - "optional": true, - "dependencies": { - "agent-base": "^6.0.0", - "debug": "4", - "http-proxy-agent": "^4.0.0", - "https-proxy-agent": "^5.0.0", - "lru-cache": "^5.1.1", - "pac-proxy-agent": "^5.0.0", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^5.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/proxy-agent/node_modules/debug": { - "version": "4.3.4", - "license": "MIT", - "optional": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/proxy-agent/node_modules/lru-cache": { - "version": "5.1.1", - "license": "ISC", - "optional": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/proxy-agent/node_modules/yallist": { - "version": "3.1.1", - "license": "ISC", - "optional": true - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "license": "MIT", - "optional": true - }, "node_modules/pstree.remy": { "version": "1.1.8", "dev": true, @@ -8101,9 +7926,10 @@ } }, "node_modules/semver": { - "version": "5.7.1", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver" } @@ -8216,9 +8042,10 @@ "license": "ISC" }, "node_modules/simple-update-notifier": { - "version": "1.0.7", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", "dev": true, - "license": "MIT", "dependencies": { "semver": "~7.0.0" }, @@ -8248,7 +8075,8 @@ }, "node_modules/smart-buffer": { "version": "4.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -8256,7 +8084,8 @@ }, "node_modules/socks": { "version": "2.7.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "dependencies": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" @@ -8266,39 +8095,6 @@ "npm": ">= 3.0.0" } }, - "node_modules/socks-proxy-agent": { - "version": "5.0.1", - "license": "MIT", - "optional": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "4", - "socks": "^2.3.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/socks-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "license": "MIT", - "optional": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socks/node_modules/ip": { - "version": "2.0.0", - "license": "MIT" - }, "node_modules/source-map": { "version": "0.6.1", "license": "BSD-3-Clause", @@ -8428,7 +8224,8 @@ }, "node_modules/strnum": { "version": "1.0.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", "optional": true }, "node_modules/superagent": { @@ -8479,9 +8276,10 @@ } }, "node_modules/superagent/node_modules/semver": { - "version": "7.3.8", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, - "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -8624,9 +8422,10 @@ "license": "MIT" }, "node_modules/tslib": { - "version": "2.4.1", - "devOptional": true, - "license": "0BSD" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "devOptional": true }, "node_modules/twostep": { "version": "0.4.2", @@ -8747,14 +8546,6 @@ "node": ">=4" } }, - "node_modules/universalify": { - "version": "0.1.2", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/unpipe": { "version": "1.0.0", "license": "MIT", @@ -8807,7 +8598,8 @@ }, "node_modules/uuid": { "version": "8.3.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "optional": true, "bin": { "uuid": "dist/bin/uuid" @@ -8840,22 +8632,6 @@ "node": ">= 0.8" } }, - "node_modules/vm2": { - "version": "3.9.17", - "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.17.tgz", - "integrity": "sha512-AqwtCnZ/ERcX+AVj9vUsphY56YANXxRuqMb7GsDtAr0m0PcQX3u0Aj3KWiXM0YAHy7i6JEeHrwOnwXbGYgRpAw==", - "optional": true, - "dependencies": { - "acorn": "^8.7.0", - "acorn-walk": "^8.2.0" - }, - "bin": { - "vm2": "bin/vm2" - }, - "engines": { - "node": ">=6.0" - } - }, "node_modules/walker": { "version": "1.0.8", "dev": true, @@ -8898,9 +8674,10 @@ } }, "node_modules/word-wrap": { - "version": "1.2.3", - "devOptional": true, - "license": "MIT", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -8971,11 +8748,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/xregexp": { - "version": "2.0.0", - "license": "MIT", - "optional": true - }, "node_modules/xtend": { "version": "4.0.2", "license": "MIT", @@ -9040,8 +8812,29 @@ "@jridgewell/trace-mapping": "^0.3.9" } }, + "@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "optional": true, + "requires": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "optional": true + } + } + }, "@aws-crypto/ie11-detection": { - "version": "2.0.2", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", "optional": true, "requires": { "tslib": "^1.11.1" @@ -9049,19 +8842,23 @@ "dependencies": { "tslib": { "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true } } }, "@aws-crypto/sha256-browser": { - "version": "2.0.0", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", "optional": true, "requires": { - "@aws-crypto/ie11-detection": "^2.0.0", - "@aws-crypto/sha256-js": "^2.0.0", - "@aws-crypto/supports-web-crypto": "^2.0.0", - "@aws-crypto/util": "^2.0.0", - "@aws-sdk/types": "^3.1.0", + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@aws-sdk/util-utf8-browser": "^3.0.0", "tslib": "^1.11.1" @@ -9069,27 +8866,35 @@ "dependencies": { "tslib": { "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true } } }, "@aws-crypto/sha256-js": { - "version": "2.0.0", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", "optional": true, "requires": { - "@aws-crypto/util": "^2.0.0", - "@aws-sdk/types": "^3.1.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", "tslib": "^1.11.1" }, "dependencies": { "tslib": { "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true } } }, "@aws-crypto/supports-web-crypto": { - "version": "2.0.2", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", "optional": true, "requires": { "tslib": "^1.11.1" @@ -9097,710 +8902,463 @@ "dependencies": { "tslib": { "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true } } }, "@aws-crypto/util": { - "version": "2.0.2", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", "optional": true, "requires": { - "@aws-sdk/types": "^3.110.0", + "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-utf8-browser": "^3.0.0", "tslib": "^1.11.1" }, "dependencies": { "tslib": { "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true - } - } - }, - "@aws-sdk/abort-controller": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/client-cognito-identity": { - "version": "3.229.0", - "optional": true, - "requires": { - "@aws-crypto/sha256-browser": "2.0.0", - "@aws-crypto/sha256-js": "2.0.0", - "@aws-sdk/client-sts": "3.229.0", - "@aws-sdk/config-resolver": "3.226.0", - "@aws-sdk/credential-provider-node": "3.229.0", - "@aws-sdk/fetch-http-handler": "3.226.0", - "@aws-sdk/hash-node": "3.226.0", - "@aws-sdk/invalid-dependency": "3.226.0", - "@aws-sdk/middleware-content-length": "3.226.0", - "@aws-sdk/middleware-endpoint": "3.226.0", - "@aws-sdk/middleware-host-header": "3.226.0", - "@aws-sdk/middleware-logger": "3.226.0", - "@aws-sdk/middleware-recursion-detection": "3.226.0", - "@aws-sdk/middleware-retry": "3.229.0", - "@aws-sdk/middleware-serde": "3.226.0", - "@aws-sdk/middleware-signing": "3.226.0", - "@aws-sdk/middleware-stack": "3.226.0", - "@aws-sdk/middleware-user-agent": "3.226.0", - "@aws-sdk/node-config-provider": "3.226.0", - "@aws-sdk/node-http-handler": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/smithy-client": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/url-parser": "3.226.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.226.0", - "@aws-sdk/util-defaults-mode-node": "3.226.0", - "@aws-sdk/util-endpoints": "3.226.0", - "@aws-sdk/util-retry": "3.229.0", - "@aws-sdk/util-user-agent-browser": "3.226.0", - "@aws-sdk/util-user-agent-node": "3.226.0", - "@aws-sdk/util-utf8-browser": "3.188.0", - "@aws-sdk/util-utf8-node": "3.208.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/client-sso": { - "version": "3.229.0", - "optional": true, - "requires": { - "@aws-crypto/sha256-browser": "2.0.0", - "@aws-crypto/sha256-js": "2.0.0", - "@aws-sdk/config-resolver": "3.226.0", - "@aws-sdk/fetch-http-handler": "3.226.0", - "@aws-sdk/hash-node": "3.226.0", - "@aws-sdk/invalid-dependency": "3.226.0", - "@aws-sdk/middleware-content-length": "3.226.0", - "@aws-sdk/middleware-endpoint": "3.226.0", - "@aws-sdk/middleware-host-header": "3.226.0", - "@aws-sdk/middleware-logger": "3.226.0", - "@aws-sdk/middleware-recursion-detection": "3.226.0", - "@aws-sdk/middleware-retry": "3.229.0", - "@aws-sdk/middleware-serde": "3.226.0", - "@aws-sdk/middleware-stack": "3.226.0", - "@aws-sdk/middleware-user-agent": "3.226.0", - "@aws-sdk/node-config-provider": "3.226.0", - "@aws-sdk/node-http-handler": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/smithy-client": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/url-parser": "3.226.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.226.0", - "@aws-sdk/util-defaults-mode-node": "3.226.0", - "@aws-sdk/util-endpoints": "3.226.0", - "@aws-sdk/util-retry": "3.229.0", - "@aws-sdk/util-user-agent-browser": "3.226.0", - "@aws-sdk/util-user-agent-node": "3.226.0", - "@aws-sdk/util-utf8-browser": "3.188.0", - "@aws-sdk/util-utf8-node": "3.208.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/client-sso-oidc": { - "version": "3.229.0", - "optional": true, - "requires": { - "@aws-crypto/sha256-browser": "2.0.0", - "@aws-crypto/sha256-js": "2.0.0", - "@aws-sdk/config-resolver": "3.226.0", - "@aws-sdk/fetch-http-handler": "3.226.0", - "@aws-sdk/hash-node": "3.226.0", - "@aws-sdk/invalid-dependency": "3.226.0", - "@aws-sdk/middleware-content-length": "3.226.0", - "@aws-sdk/middleware-endpoint": "3.226.0", - "@aws-sdk/middleware-host-header": "3.226.0", - "@aws-sdk/middleware-logger": "3.226.0", - "@aws-sdk/middleware-recursion-detection": "3.226.0", - "@aws-sdk/middleware-retry": "3.229.0", - "@aws-sdk/middleware-serde": "3.226.0", - "@aws-sdk/middleware-stack": "3.226.0", - "@aws-sdk/middleware-user-agent": "3.226.0", - "@aws-sdk/node-config-provider": "3.226.0", - "@aws-sdk/node-http-handler": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/smithy-client": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/url-parser": "3.226.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.226.0", - "@aws-sdk/util-defaults-mode-node": "3.226.0", - "@aws-sdk/util-endpoints": "3.226.0", - "@aws-sdk/util-retry": "3.229.0", - "@aws-sdk/util-user-agent-browser": "3.226.0", - "@aws-sdk/util-user-agent-node": "3.226.0", - "@aws-sdk/util-utf8-browser": "3.188.0", - "@aws-sdk/util-utf8-node": "3.208.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/client-sts": { - "version": "3.229.0", - "optional": true, - "requires": { - "@aws-crypto/sha256-browser": "2.0.0", - "@aws-crypto/sha256-js": "2.0.0", - "@aws-sdk/config-resolver": "3.226.0", - "@aws-sdk/credential-provider-node": "3.229.0", - "@aws-sdk/fetch-http-handler": "3.226.0", - "@aws-sdk/hash-node": "3.226.0", - "@aws-sdk/invalid-dependency": "3.226.0", - "@aws-sdk/middleware-content-length": "3.226.0", - "@aws-sdk/middleware-endpoint": "3.226.0", - "@aws-sdk/middleware-host-header": "3.226.0", - "@aws-sdk/middleware-logger": "3.226.0", - "@aws-sdk/middleware-recursion-detection": "3.226.0", - "@aws-sdk/middleware-retry": "3.229.0", - "@aws-sdk/middleware-sdk-sts": "3.226.0", - "@aws-sdk/middleware-serde": "3.226.0", - "@aws-sdk/middleware-signing": "3.226.0", - "@aws-sdk/middleware-stack": "3.226.0", - "@aws-sdk/middleware-user-agent": "3.226.0", - "@aws-sdk/node-config-provider": "3.226.0", - "@aws-sdk/node-http-handler": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/smithy-client": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/url-parser": "3.226.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.226.0", - "@aws-sdk/util-defaults-mode-node": "3.226.0", - "@aws-sdk/util-endpoints": "3.226.0", - "@aws-sdk/util-retry": "3.229.0", - "@aws-sdk/util-user-agent-browser": "3.226.0", - "@aws-sdk/util-user-agent-node": "3.226.0", - "@aws-sdk/util-utf8-browser": "3.188.0", - "@aws-sdk/util-utf8-node": "3.208.0", - "fast-xml-parser": "4.0.11", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/config-resolver": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/signature-v4": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/util-config-provider": "3.208.0", - "@aws-sdk/util-middleware": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/credential-provider-cognito-identity": { - "version": "3.229.0", - "optional": true, - "requires": { - "@aws-sdk/client-cognito-identity": "3.229.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/credential-provider-env": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/credential-provider-imds": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/node-config-provider": "3.226.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/url-parser": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/credential-provider-ini": { - "version": "3.229.0", - "optional": true, - "requires": { - "@aws-sdk/credential-provider-env": "3.226.0", - "@aws-sdk/credential-provider-imds": "3.226.0", - "@aws-sdk/credential-provider-sso": "3.229.0", - "@aws-sdk/credential-provider-web-identity": "3.226.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/shared-ini-file-loader": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/credential-provider-node": { - "version": "3.229.0", - "optional": true, - "requires": { - "@aws-sdk/credential-provider-env": "3.226.0", - "@aws-sdk/credential-provider-imds": "3.226.0", - "@aws-sdk/credential-provider-ini": "3.229.0", - "@aws-sdk/credential-provider-process": "3.226.0", - "@aws-sdk/credential-provider-sso": "3.229.0", - "@aws-sdk/credential-provider-web-identity": "3.226.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/shared-ini-file-loader": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/credential-provider-process": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/shared-ini-file-loader": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/credential-provider-sso": { - "version": "3.229.0", - "optional": true, - "requires": { - "@aws-sdk/client-sso": "3.229.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/shared-ini-file-loader": "3.226.0", - "@aws-sdk/token-providers": "3.229.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/credential-provider-web-identity": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/credential-providers": { - "version": "3.229.0", - "optional": true, - "requires": { - "@aws-sdk/client-cognito-identity": "3.229.0", - "@aws-sdk/client-sso": "3.229.0", - "@aws-sdk/client-sts": "3.229.0", - "@aws-sdk/credential-provider-cognito-identity": "3.229.0", - "@aws-sdk/credential-provider-env": "3.226.0", - "@aws-sdk/credential-provider-imds": "3.226.0", - "@aws-sdk/credential-provider-ini": "3.229.0", - "@aws-sdk/credential-provider-node": "3.229.0", - "@aws-sdk/credential-provider-process": "3.226.0", - "@aws-sdk/credential-provider-sso": "3.229.0", - "@aws-sdk/credential-provider-web-identity": "3.226.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/shared-ini-file-loader": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/fetch-http-handler": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/querystring-builder": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/util-base64": "3.208.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/hash-node": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/types": "3.226.0", - "@aws-sdk/util-buffer-from": "3.208.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/invalid-dependency": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/is-array-buffer": { - "version": "3.201.0", - "optional": true, - "requires": { - "tslib": "^2.3.1" - } - }, - "@aws-sdk/middleware-content-length": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/middleware-endpoint": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/middleware-serde": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/signature-v4": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/url-parser": "3.226.0", - "@aws-sdk/util-config-provider": "3.208.0", - "@aws-sdk/util-middleware": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/middleware-host-header": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/middleware-logger": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/middleware-recursion-detection": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/middleware-retry": { - "version": "3.229.0", - "optional": true, - "requires": { - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/service-error-classification": "3.229.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/util-middleware": "3.226.0", - "tslib": "^2.3.1", - "uuid": "^8.3.2" - } - }, - "@aws-sdk/middleware-sdk-sts": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/middleware-signing": "3.226.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/signature-v4": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/middleware-serde": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/middleware-signing": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/signature-v4": "3.226.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/util-middleware": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/middleware-stack": { - "version": "3.226.0", - "optional": true, - "requires": { - "tslib": "^2.3.1" - } - }, - "@aws-sdk/middleware-user-agent": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/node-config-provider": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/shared-ini-file-loader": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/node-http-handler": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/abort-controller": "3.226.0", - "@aws-sdk/protocol-http": "3.226.0", - "@aws-sdk/querystring-builder": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/property-provider": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/protocol-http": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + } } }, - "@aws-sdk/querystring-builder": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/types": "3.226.0", - "@aws-sdk/util-uri-escape": "3.201.0", - "tslib": "^2.3.1" + "@aws-sdk/client-cognito-identity": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.398.0.tgz", + "integrity": "sha512-Pr/S1f8R2FsJ8DwBC6g0CSdtZNNV5dMHhlIi+t8YAmCJvP4KT+UhzFjbvQRINlBRLFuGUuP7p5vRcGVELD3+wA==", + "optional": true, + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.398.0", + "@aws-sdk/credential-provider-node": "3.398.0", + "@aws-sdk/middleware-host-header": "3.398.0", + "@aws-sdk/middleware-logger": "3.398.0", + "@aws-sdk/middleware-recursion-detection": "3.398.0", + "@aws-sdk/middleware-signing": "3.398.0", + "@aws-sdk/middleware-user-agent": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@aws-sdk/util-endpoints": "3.398.0", + "@aws-sdk/util-user-agent-browser": "3.398.0", + "@aws-sdk/util-user-agent-node": "3.398.0", + "@smithy/config-resolver": "^2.0.5", + "@smithy/fetch-http-handler": "^2.0.5", + "@smithy/hash-node": "^2.0.5", + "@smithy/invalid-dependency": "^2.0.5", + "@smithy/middleware-content-length": "^2.0.5", + "@smithy/middleware-endpoint": "^2.0.5", + "@smithy/middleware-retry": "^2.0.5", + "@smithy/middleware-serde": "^2.0.5", + "@smithy/middleware-stack": "^2.0.0", + "@smithy/node-config-provider": "^2.0.5", + "@smithy/node-http-handler": "^2.0.5", + "@smithy/protocol-http": "^2.0.5", + "@smithy/smithy-client": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/url-parser": "^2.0.5", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.5", + "@smithy/util-defaults-mode-node": "^2.0.5", + "@smithy/util-retry": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" } }, - "@aws-sdk/querystring-parser": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/client-sso": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.398.0.tgz", + "integrity": "sha512-CygL0jhfibw4kmWXG/3sfZMFNjcXo66XUuPC4BqZBk8Rj5vFoxp1vZeMkDLzTIk97Nvo5J5Bh+QnXKhub6AckQ==", + "optional": true, + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.398.0", + "@aws-sdk/middleware-logger": "3.398.0", + "@aws-sdk/middleware-recursion-detection": "3.398.0", + "@aws-sdk/middleware-user-agent": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@aws-sdk/util-endpoints": "3.398.0", + "@aws-sdk/util-user-agent-browser": "3.398.0", + "@aws-sdk/util-user-agent-node": "3.398.0", + "@smithy/config-resolver": "^2.0.5", + "@smithy/fetch-http-handler": "^2.0.5", + "@smithy/hash-node": "^2.0.5", + "@smithy/invalid-dependency": "^2.0.5", + "@smithy/middleware-content-length": "^2.0.5", + "@smithy/middleware-endpoint": "^2.0.5", + "@smithy/middleware-retry": "^2.0.5", + "@smithy/middleware-serde": "^2.0.5", + "@smithy/middleware-stack": "^2.0.0", + "@smithy/node-config-provider": "^2.0.5", + "@smithy/node-http-handler": "^2.0.5", + "@smithy/protocol-http": "^2.0.5", + "@smithy/smithy-client": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/url-parser": "^2.0.5", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.5", + "@smithy/util-defaults-mode-node": "^2.0.5", + "@smithy/util-retry": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" } }, - "@aws-sdk/service-error-classification": { - "version": "3.229.0", - "optional": true - }, - "@aws-sdk/shared-ini-file-loader": { - "version": "3.226.0", - "optional": true, - "requires": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/client-sts": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.398.0.tgz", + "integrity": "sha512-/3Pa9wLMvBZipKraq3AtbmTfXW6q9kyvhwOno64f1Fz7kFb8ijQFMGoATS70B2pGEZTlxkUqJFWDiisT6Q6dFg==", + "optional": true, + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/credential-provider-node": "3.398.0", + "@aws-sdk/middleware-host-header": "3.398.0", + "@aws-sdk/middleware-logger": "3.398.0", + "@aws-sdk/middleware-recursion-detection": "3.398.0", + "@aws-sdk/middleware-sdk-sts": "3.398.0", + "@aws-sdk/middleware-signing": "3.398.0", + "@aws-sdk/middleware-user-agent": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@aws-sdk/util-endpoints": "3.398.0", + "@aws-sdk/util-user-agent-browser": "3.398.0", + "@aws-sdk/util-user-agent-node": "3.398.0", + "@smithy/config-resolver": "^2.0.5", + "@smithy/fetch-http-handler": "^2.0.5", + "@smithy/hash-node": "^2.0.5", + "@smithy/invalid-dependency": "^2.0.5", + "@smithy/middleware-content-length": "^2.0.5", + "@smithy/middleware-endpoint": "^2.0.5", + "@smithy/middleware-retry": "^2.0.5", + "@smithy/middleware-serde": "^2.0.5", + "@smithy/middleware-stack": "^2.0.0", + "@smithy/node-config-provider": "^2.0.5", + "@smithy/node-http-handler": "^2.0.5", + "@smithy/protocol-http": "^2.0.5", + "@smithy/smithy-client": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/url-parser": "^2.0.5", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.5", + "@smithy/util-defaults-mode-node": "^2.0.5", + "@smithy/util-retry": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" } }, - "@aws-sdk/signature-v4": { - "version": "3.226.0", + "@aws-sdk/credential-provider-cognito-identity": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.398.0.tgz", + "integrity": "sha512-MFUhy1YayHg5ypRTk4OTfDumQRP+OJBagaGv14kA8DzhKH1sNrU4HV7A7y2J4SvkN5hG/KnLJqxpakCtB2/O2g==", "optional": true, "requires": { - "@aws-sdk/is-array-buffer": "3.201.0", - "@aws-sdk/types": "3.226.0", - "@aws-sdk/util-hex-encoding": "3.201.0", - "@aws-sdk/util-middleware": "3.226.0", - "@aws-sdk/util-uri-escape": "3.201.0", - "tslib": "^2.3.1" + "@aws-sdk/client-cognito-identity": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@aws-sdk/smithy-client": { - "version": "3.226.0", + "@aws-sdk/credential-provider-env": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.398.0.tgz", + "integrity": "sha512-Z8Yj5z7FroAsR6UVML+XUdlpoqEe9Dnle8c2h8/xWwIC2feTfIBhjLhRVxfbpbM1pLgBSNEcZ7U8fwq5l7ESVQ==", "optional": true, "requires": { - "@aws-sdk/middleware-stack": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@aws-sdk/token-providers": { - "version": "3.229.0", + "@aws-sdk/credential-provider-ini": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.398.0.tgz", + "integrity": "sha512-AsK1lStK3nB9Cn6S6ODb1ktGh7SRejsNVQVKX3t5d3tgOaX+aX1Iwy8FzM/ZEN8uCloeRifUGIY9uQFygg5mSw==", "optional": true, "requires": { - "@aws-sdk/client-sso-oidc": "3.229.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/shared-ini-file-loader": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/credential-provider-env": "3.398.0", + "@aws-sdk/credential-provider-process": "3.398.0", + "@aws-sdk/credential-provider-sso": "3.398.0", + "@aws-sdk/credential-provider-web-identity": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@aws-sdk/types": { - "version": "3.226.0", + "@aws-sdk/credential-provider-node": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.398.0.tgz", + "integrity": "sha512-odmI/DSKfuWUYeDnGTCEHBbC8/MwnF6yEq874zl6+owoVv0ZsYP8qBHfiJkYqrwg7wQ7Pi40sSAPC1rhesGwzg==", "optional": true, "requires": { - "tslib": "^2.3.1" + "@aws-sdk/credential-provider-env": "3.398.0", + "@aws-sdk/credential-provider-ini": "3.398.0", + "@aws-sdk/credential-provider-process": "3.398.0", + "@aws-sdk/credential-provider-sso": "3.398.0", + "@aws-sdk/credential-provider-web-identity": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@aws-sdk/url-parser": { - "version": "3.226.0", + "@aws-sdk/credential-provider-process": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.398.0.tgz", + "integrity": "sha512-WrkBL1W7TXN508PA9wRXPFtzmGpVSW98gDaHEaa8GolAPHMPa5t2QcC/z/cFpglzrcVv8SA277zu9Z8tELdZhg==", "optional": true, "requires": { - "@aws-sdk/querystring-parser": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@aws-sdk/util-base64": { - "version": "3.208.0", + "@aws-sdk/credential-provider-sso": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.398.0.tgz", + "integrity": "sha512-2Dl35587xbnzR/GGZqA2MnFs8+kS4wbHQO9BioU0okA+8NRueohNMdrdQmQDdSNK4BfIpFspiZmFkXFNyEAfgw==", "optional": true, "requires": { - "@aws-sdk/util-buffer-from": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/client-sso": "3.398.0", + "@aws-sdk/token-providers": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@aws-sdk/util-body-length-browser": { - "version": "3.188.0", + "@aws-sdk/credential-provider-web-identity": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.398.0.tgz", + "integrity": "sha512-iG3905Alv9pINbQ8/MIsshgqYMbWx+NDQWpxbIW3W0MkSH3iAqdVpSCteYidYX9G/jv2Um1nW3y360ib20bvNg==", "optional": true, "requires": { - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@aws-sdk/util-body-length-node": { - "version": "3.208.0", - "optional": true, - "requires": { - "tslib": "^2.3.1" + "@aws-sdk/credential-providers": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.398.0.tgz", + "integrity": "sha512-355vXmImn2e85mIWSYDVb101AF2lIVHKNCaH6sV1U/8i0ZOXh2cJYNdkRYrxNt1ezDB0k97lSKvuDx7RDvJyRg==", + "optional": true, + "requires": { + "@aws-sdk/client-cognito-identity": "3.398.0", + "@aws-sdk/client-sso": "3.398.0", + "@aws-sdk/client-sts": "3.398.0", + "@aws-sdk/credential-provider-cognito-identity": "3.398.0", + "@aws-sdk/credential-provider-env": "3.398.0", + "@aws-sdk/credential-provider-ini": "3.398.0", + "@aws-sdk/credential-provider-node": "3.398.0", + "@aws-sdk/credential-provider-process": "3.398.0", + "@aws-sdk/credential-provider-sso": "3.398.0", + "@aws-sdk/credential-provider-web-identity": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@aws-sdk/util-buffer-from": { - "version": "3.208.0", + "@aws-sdk/middleware-host-header": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.398.0.tgz", + "integrity": "sha512-m+5laWdBaxIZK2ko0OwcCHJZJ5V1MgEIt8QVQ3k4/kOkN9ICjevOYmba751pHoTnbOYB7zQd6D2OT3EYEEsUcA==", "optional": true, "requires": { - "@aws-sdk/is-array-buffer": "3.201.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/protocol-http": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@aws-sdk/util-config-provider": { - "version": "3.208.0", + "@aws-sdk/middleware-logger": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.398.0.tgz", + "integrity": "sha512-CiJjW+FL12elS6Pn7/UVjVK8HWHhXMfvHZvOwx/Qkpy340sIhkuzOO6fZEruECDTZhl2Wqn81XdJ1ZQ4pRKpCg==", "optional": true, "requires": { - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@aws-sdk/util-defaults-mode-browser": { - "version": "3.226.0", + "@aws-sdk/middleware-recursion-detection": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.398.0.tgz", + "integrity": "sha512-7QpOqPQAZNXDXv6vsRex4R8dLniL0E/80OPK4PPFsrCh9btEyhN9Begh4i1T+5lL28hmYkztLOkTQ2N5J3hgRQ==", "optional": true, "requires": { - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/types": "3.226.0", - "bowser": "^2.11.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/protocol-http": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@aws-sdk/util-defaults-mode-node": { - "version": "3.226.0", + "@aws-sdk/middleware-sdk-sts": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.398.0.tgz", + "integrity": "sha512-+JH76XHEgfVihkY+GurohOQ5Z83zVN1nYcQzwCFnCDTh4dG4KwhnZKG+WPw6XJECocY0R+H0ivofeALHvVWJtQ==", "optional": true, "requires": { - "@aws-sdk/config-resolver": "3.226.0", - "@aws-sdk/credential-provider-imds": "3.226.0", - "@aws-sdk/node-config-provider": "3.226.0", - "@aws-sdk/property-provider": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/middleware-signing": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@aws-sdk/util-endpoints": { - "version": "3.226.0", + "@aws-sdk/middleware-signing": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.398.0.tgz", + "integrity": "sha512-O0KqXAix1TcvZBFt1qoFkHMUNJOSgjJTYS7lFTRKSwgsD27bdW2TM2r9R8DAccWFt5Amjkdt+eOwQMIXPGTm8w==", "optional": true, "requires": { - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^2.0.5", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.2.2", + "@smithy/util-middleware": "^2.0.0", + "tslib": "^2.5.0" } }, - "@aws-sdk/util-hex-encoding": { - "version": "3.201.0", + "@aws-sdk/middleware-user-agent": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.398.0.tgz", + "integrity": "sha512-nF1jg0L+18b5HvTcYzwyFgfZQQMELJINFqI0mi4yRKaX7T5a3aGp5RVLGGju/6tAGTuFbfBoEhkhU3kkxexPYQ==", "optional": true, "requires": { - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@aws-sdk/util-endpoints": "3.398.0", + "@smithy/protocol-http": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@aws-sdk/util-locate-window": { - "version": "3.208.0", - "optional": true, - "requires": { - "tslib": "^2.3.1" + "@aws-sdk/token-providers": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.398.0.tgz", + "integrity": "sha512-nrYgjzavGCKJL/48Vt0EL+OlIc5UZLfNGpgyUW9cv3XZwl+kXV0QB+HH0rHZZLfpbBgZ2RBIJR9uD5ieu/6hpQ==", + "optional": true, + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.398.0", + "@aws-sdk/middleware-logger": "3.398.0", + "@aws-sdk/middleware-recursion-detection": "3.398.0", + "@aws-sdk/middleware-user-agent": "3.398.0", + "@aws-sdk/types": "3.398.0", + "@aws-sdk/util-endpoints": "3.398.0", + "@aws-sdk/util-user-agent-browser": "3.398.0", + "@aws-sdk/util-user-agent-node": "3.398.0", + "@smithy/config-resolver": "^2.0.5", + "@smithy/fetch-http-handler": "^2.0.5", + "@smithy/hash-node": "^2.0.5", + "@smithy/invalid-dependency": "^2.0.5", + "@smithy/middleware-content-length": "^2.0.5", + "@smithy/middleware-endpoint": "^2.0.5", + "@smithy/middleware-retry": "^2.0.5", + "@smithy/middleware-serde": "^2.0.5", + "@smithy/middleware-stack": "^2.0.0", + "@smithy/node-config-provider": "^2.0.5", + "@smithy/node-http-handler": "^2.0.5", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^2.0.5", + "@smithy/shared-ini-file-loader": "^2.0.0", + "@smithy/smithy-client": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/url-parser": "^2.0.5", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.5", + "@smithy/util-defaults-mode-node": "^2.0.5", + "@smithy/util-retry": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" } }, - "@aws-sdk/util-middleware": { - "version": "3.226.0", + "@aws-sdk/types": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.398.0.tgz", + "integrity": "sha512-r44fkS+vsEgKCuEuTV+TIk0t0m5ZlXHNjSDYEUvzLStbbfUFiNus/YG4UCa0wOk9R7VuQI67badsvvPeVPCGDQ==", "optional": true, "requires": { - "tslib": "^2.3.1" + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@aws-sdk/util-retry": { - "version": "3.229.0", + "@aws-sdk/util-endpoints": { + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.398.0.tgz", + "integrity": "sha512-Fy0gLYAei/Rd6BrXG4baspCnWTUSd0NdokU1pZh4KlfEAEN1i8SPPgfiO5hLk7+2inqtCmqxVJlfqbMVe9k4bw==", "optional": true, "requires": { - "@aws-sdk/service-error-classification": "3.229.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "tslib": "^2.5.0" } }, - "@aws-sdk/util-uri-escape": { - "version": "3.201.0", + "@aws-sdk/util-locate-window": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", "optional": true, "requires": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/util-user-agent-browser": { - "version": "3.226.0", + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.398.0.tgz", + "integrity": "sha512-A3Tzx1tkDHlBT+IgxmsMCHbV8LM7SwwCozq2ZjJRx0nqw3MCrrcxQFXldHeX/gdUMO+0Oocb7HGSnVODTq+0EA==", "optional": true, "requires": { - "@aws-sdk/types": "3.226.0", + "@aws-sdk/types": "3.398.0", + "@smithy/types": "^2.2.2", "bowser": "^2.11.0", - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/util-user-agent-node": { - "version": "3.226.0", + "version": "3.398.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.398.0.tgz", + "integrity": "sha512-RTVQofdj961ej4//fEkppFf4KXqKGMTCqJYghx3G0C/MYXbg7MGl7LjfNGtJcboRE8pfHHQ/TUWBDA7RIAPPlQ==", "optional": true, "requires": { - "@aws-sdk/node-config-provider": "3.226.0", - "@aws-sdk/types": "3.226.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.398.0", + "@smithy/node-config-provider": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, "@aws-sdk/util-utf8-browser": { - "version": "3.188.0", - "optional": true, - "requires": { - "tslib": "^2.3.1" - } - }, - "@aws-sdk/util-utf8-node": { - "version": "3.208.0", + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", "optional": true, "requires": { - "@aws-sdk/util-buffer-from": "3.208.0", "tslib": "^2.3.1" } }, @@ -9840,7 +9398,9 @@ } }, "semver": { - "version": "6.3.0" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -9887,7 +9447,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -9932,7 +9494,9 @@ } }, "semver": { - "version": "6.3.0", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -10691,7 +10255,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -11079,55 +10645,477 @@ }, "dependencies": { "semver": { - "version": "7.3.8", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } } } }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, + "@mongodb-js/saslprep": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", + "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@sinclair/typebox": { + "version": "0.25.24", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", + "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==" + }, + "@sinonjs/commons": { + "version": "1.8.6", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "9.1.2", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@smithy/abort-controller": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.5.tgz", + "integrity": "sha512-byVZ2KWLMPYAZGKjRpniAzLcygJO4ruClZKdJTuB0eCB76ONFTdptBHlviHpAZXknRz7skYWPfcgO9v30A1SyA==", + "optional": true, + "requires": { + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" + } + }, + "@smithy/config-resolver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.5.tgz", + "integrity": "sha512-n0c2AXz+kjALY2FQr7Zy9zhYigXzboIh1AuUUVCqFBKFtdEvTwnwPXrTDoEehLiRTUHNL+4yzZ3s+D0kKYSLSg==", + "optional": true, + "requires": { + "@smithy/types": "^2.2.2", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/credential-provider-imds": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.5.tgz", + "integrity": "sha512-KFcf/e0meFkQNyteJ65f1G19sgUEY1e5zL7hyAEUPz2SEfBmC9B37WyRq87G3MEEsvmAWwCRu7nFFYUKtR3svQ==", + "optional": true, + "requires": { + "@smithy/node-config-provider": "^2.0.5", + "@smithy/property-provider": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/url-parser": "^2.0.5", + "tslib": "^2.5.0" + } + }, + "@smithy/eventstream-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.5.tgz", + "integrity": "sha512-iqR6OuOV3zbQK8uVs9o+9AxhVk8kW9NAxA71nugwUB+kTY9C35pUd0A5/m4PRT0Y0oIW7W4kgnSR3fdYXQjECw==", + "optional": true, + "requires": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.2.2", + "@smithy/util-hex-encoding": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/fetch-http-handler": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.0.5.tgz", + "integrity": "sha512-EzFoMowdBNy1VqtvkiXgPFEdosIAt4/4bgZ8uiDiUyfhmNXq/3bV+CagPFFBsgFOR/X2XK4zFZHRsoa7PNHVVg==", + "optional": true, + "requires": { + "@smithy/protocol-http": "^2.0.5", + "@smithy/querystring-builder": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/util-base64": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/hash-node": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.5.tgz", + "integrity": "sha512-mk551hIywBITT+kXruRNXk7f8Fy7DTzBjZJSr/V6nolYKmUHIG3w5QU6nO9qPYEQGKc/yEPtkpdS28ndeG93lA==", + "optional": true, + "requires": { + "@smithy/types": "^2.2.2", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/invalid-dependency": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.5.tgz", + "integrity": "sha512-0wEi+JT0hM+UUwrJVYbqjuGFhy5agY/zXyiN7BNAJ1XoCDjU5uaNSj8ekPWsXd/d4yM6NSe8UbPd8cOc1+3oBQ==", + "optional": true, + "requires": { + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" + } + }, + "@smithy/is-array-buffer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", + "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/middleware-content-length": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.5.tgz", + "integrity": "sha512-E7VwV5H02fgZIUGRli4GevBCAPvkyEI/fgl9SU47nPPi3DAAX3nEtUb8xfGbXjOcJ5BdSUoWWZn42tEd/blOqA==", + "optional": true, + "requires": { + "@smithy/protocol-http": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" + } + }, + "@smithy/middleware-endpoint": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.0.5.tgz", + "integrity": "sha512-tyzDuoNTbsMQCq5Xkc4QOt6e2GACUllQIV8SQ5fc59FtOIV9/vbf58/GxVjZm2o8+MMbdDBANjTDZe/ijZKfyA==", + "optional": true, + "requires": { + "@smithy/middleware-serde": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/url-parser": "^2.0.5", + "@smithy/util-middleware": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/middleware-retry": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.5.tgz", + "integrity": "sha512-ulIfbFyzQTVnJbLjUl1CTSi0etg6tej/ekwaLp0Gn8ybUkDkKYa+uB6CF/m2J5B6meRwyJlsryR+DjaOVyiicg==", + "optional": true, + "requires": { + "@smithy/protocol-http": "^2.0.5", + "@smithy/service-error-classification": "^2.0.0", + "@smithy/types": "^2.2.2", + "@smithy/util-middleware": "^2.0.0", + "@smithy/util-retry": "^2.0.0", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + } + }, + "@smithy/middleware-serde": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.5.tgz", + "integrity": "sha512-in0AA5sous74dOfTGU9rMJBXJ0bDVNxwdXtEt5lh3FVd2sEyjhI+rqpLLRF1E4ixbw3RSEf80hfRpcPdjg4vvQ==", + "optional": true, + "requires": { + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" + } + }, + "@smithy/middleware-stack": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.0.tgz", + "integrity": "sha512-31XC1xNF65nlbc16yuh3wwTudmqs6qy4EseQUGF8A/p2m/5wdd/cnXJqpniy/XvXVwkHPz/GwV36HqzHtIKATQ==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/node-config-provider": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.0.5.tgz", + "integrity": "sha512-LRtjV9WkhONe2lVy+ipB/l1GX60ybzBmFyeRUoLUXWKdnZ3o81jsnbKzMK8hKq8eFSWPk+Lmyx6ZzCQabGeLxg==", + "optional": true, + "requires": { + "@smithy/property-provider": "^2.0.5", + "@smithy/shared-ini-file-loader": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" + } + }, + "@smithy/node-http-handler": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.0.5.tgz", + "integrity": "sha512-lZm5DZf4b3V0saUw9WTC4/du887P6cy2fUyQgQQKRRV6OseButyD5yTzeMmXE53CaXJBMBsUvvIQ0hRVxIq56w==", + "optional": true, + "requires": { + "@smithy/abort-controller": "^2.0.5", + "@smithy/protocol-http": "^2.0.5", + "@smithy/querystring-builder": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" + } + }, + "@smithy/property-provider": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.5.tgz", + "integrity": "sha512-cAFSUhX6aiHcmpWfrCLKvwBtgN1F6A0N8qY/8yeSi0LRLmhGqsY1/YTxFE185MCVzYbqBGXVr9TBv4RUcIV4rA==", + "optional": true, + "requires": { + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" + } + }, + "@smithy/protocol-http": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-2.0.5.tgz", + "integrity": "sha512-d2hhHj34mA2V86doiDfrsy2fNTnUOowGaf9hKb0hIPHqvcnShU4/OSc4Uf1FwHkAdYF3cFXTrj5VGUYbEuvMdw==", + "optional": true, + "requires": { + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" + } + }, + "@smithy/querystring-builder": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.5.tgz", + "integrity": "sha512-4DCX9krxLzATj+HdFPC3i8pb7XTAWzzKqSw8aTZMjXjtQY+vhe4azMAqIvbb6g7JKwIkmkRAjK6EXO3YWSnJVQ==", + "optional": true, + "requires": { + "@smithy/types": "^2.2.2", + "@smithy/util-uri-escape": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/querystring-parser": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.5.tgz", + "integrity": "sha512-C2stCULH0r54KBksv3AWcN8CLS3u9+WsEW8nBrvctrJ5rQTNa1waHkffpVaiKvcW2nP0aIMBPCobD/kYf/q9mA==", + "optional": true, + "requires": { + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" + } + }, + "@smithy/service-error-classification": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.0.tgz", + "integrity": "sha512-2z5Nafy1O0cTf69wKyNjGW/sNVMiqDnb4jgwfMG8ye8KnFJ5qmJpDccwIbJNhXIfbsxTg9SEec2oe1cexhMJvw==", + "optional": true + }, + "@smithy/shared-ini-file-loader": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.0.5.tgz", + "integrity": "sha512-Mvtk6FwMtfbKRC4YuSsIqRYp9WTxsSUJVVo2djgyhcacKGMqicHDWSAmgy3sDrKv+G/G6xTZCPwm6pJARtdxVg==", + "optional": true, + "requires": { + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" + } + }, + "@smithy/signature-v4": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.5.tgz", + "integrity": "sha512-ABIzXmUDXK4n2c9cXjQLELgH2RdtABpYKT+U131e2I6RbCypFZmxIHmIBufJzU2kdMCQ3+thBGDWorAITFW04A==", + "optional": true, + "requires": { + "@smithy/eventstream-codec": "^2.0.5", + "@smithy/is-array-buffer": "^2.0.0", + "@smithy/types": "^2.2.2", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-middleware": "^2.0.0", + "@smithy/util-uri-escape": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/smithy-client": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.0.5.tgz", + "integrity": "sha512-kCTFr8wfOAWKDzGvfBElc6shHigWtHNhMQ1IbosjC4jOlayFyZMSs2PysKB+Ox/dhQ41KqOzgVjgiQ+PyWqHMQ==", + "optional": true, + "requires": { + "@smithy/middleware-stack": "^2.0.0", + "@smithy/types": "^2.2.2", + "@smithy/util-stream": "^2.0.5", + "tslib": "^2.5.0" + } + }, + "@smithy/types": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.2.2.tgz", + "integrity": "sha512-4PS0y1VxDnELGHGgBWlDksB2LJK8TG8lcvlWxIsgR+8vROI7Ms8h1P4FQUx+ftAX2QZv5g1CJCdhdRmQKyonyw==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/url-parser": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.5.tgz", + "integrity": "sha512-OdMBvZhpckQSkugCXNJQCvqJ71wE7Ftxce92UOQLQ9pwF6hoS5PLL7wEfpnuEXtStzBqJYkzu1C1ZfjuFGOXAA==", + "optional": true, + "requires": { + "@smithy/querystring-parser": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" + } + }, + "@smithy/util-base64": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.0.tgz", + "integrity": "sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==", + "optional": true, + "requires": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-body-length-browser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", + "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/util-body-length-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", + "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/util-buffer-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", + "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "optional": true, + "requires": { + "@smithy/is-array-buffer": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-config-provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", + "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", + "optional": true, "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "tslib": "^2.5.0" } }, - "@nodelib/fs.stat": { + "@smithy/util-defaults-mode-browser": { "version": "2.0.5", - "dev": true + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.5.tgz", + "integrity": "sha512-yciP6TPttLsj731aHTvekgyuCGXQrEAJibEwEWAh3kzaDsfGAVCuZSBlyvC2Dl3TZmHKCOQwHV8mIE7KQCTPuQ==", + "optional": true, + "requires": { + "@smithy/property-provider": "^2.0.5", + "@smithy/types": "^2.2.2", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + } }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, + "@smithy/util-defaults-mode-node": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.5.tgz", + "integrity": "sha512-M07t99rWasXt+IaDZDyP3BkcoEm/mgIE1RIMASrE49LKSNxaVN7PVcgGc77+4uu2kzBAyqJKy79pgtezuknyjQ==", + "optional": true, "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@smithy/config-resolver": "^2.0.5", + "@smithy/credential-provider-imds": "^2.0.5", + "@smithy/node-config-provider": "^2.0.5", + "@smithy/property-provider": "^2.0.5", + "@smithy/types": "^2.2.2", + "tslib": "^2.5.0" } }, - "@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==" + "@smithy/util-hex-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", + "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + } }, - "@sinonjs/commons": { - "version": "1.8.6", - "dev": true, + "@smithy/util-middleware": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.0.tgz", + "integrity": "sha512-eCWX4ECuDHn1wuyyDdGdUWnT4OGyIzV0LN1xRttBFMPI9Ff/4heSHVxneyiMtOB//zpXWCha1/SWHJOZstG7kA==", + "optional": true, "requires": { - "type-detect": "4.0.8" + "tslib": "^2.5.0" } }, - "@sinonjs/fake-timers": { - "version": "9.1.2", - "dev": true, + "@smithy/util-retry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.0.tgz", + "integrity": "sha512-/dvJ8afrElasuiiIttRJeoS2sy8YXpksQwiM/TcepqdRVp7u4ejd9C4IQURHNjlfPUT7Y6lCDSa2zQJbdHhVTg==", + "optional": true, "requires": { - "@sinonjs/commons": "^1.7.0" + "@smithy/service-error-classification": "^2.0.0", + "tslib": "^2.5.0" } }, - "@tootallnate/once": { - "version": "1.1.2", - "optional": true + "@smithy/util-stream": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.5.tgz", + "integrity": "sha512-ylx27GwI05xLpYQ4hDIfS15vm+wYjNN0Sc2P0FxuzgRe8v0BOLHppGIQ+Bezcynk8C9nUzsUue3TmtRhjut43g==", + "optional": true, + "requires": { + "@smithy/fetch-http-handler": "^2.0.5", + "@smithy/node-http-handler": "^2.0.5", + "@smithy/types": "^2.2.2", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-uri-escape": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", + "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/util-utf8": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", + "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", + "optional": true, + "requires": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + } }, "@types/babel__core": { "version": "7.1.16", @@ -11205,10 +11193,14 @@ "version": "2.0.1" }, "@types/webidl-conversions": { - "version": "7.0.0" + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" }, "@types/whatwg-url": { "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", "requires": { "@types/node": "*", "@types/webidl-conversions": "*" @@ -11235,17 +11227,13 @@ }, "acorn": { "version": "8.8.1", - "devOptional": true + "dev": true }, "acorn-jsx": { "version": "5.3.2", "dev": true, "requires": {} }, - "acorn-walk": { - "version": "8.2.0", - "optional": true - }, "agent-base": { "version": "6.0.2", "requires": { @@ -11337,13 +11325,6 @@ "version": "2.0.6", "dev": true }, - "ast-types": { - "version": "0.13.4", - "optional": true, - "requires": { - "tslib": "^2.0.1" - } - }, "asynckit": { "version": "0.4.0", "dev": true @@ -11395,7 +11376,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -11453,7 +11436,9 @@ "version": "1.0.0" }, "base64-js": { - "version": "1.5.1" + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "base64url": { "version": "3.0.1" @@ -11521,6 +11506,8 @@ }, "bowser": { "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", "optional": true }, "brace-expansion": { @@ -11557,6 +11544,8 @@ }, "buffer": { "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "requires": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -11593,7 +11582,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001439" + "version": "1.0.30001524", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001524.tgz", + "integrity": "sha512-Jj917pJtYg9HSJBF95HVX3Cdr89JUyLT4IZ8SvM5aDRni95swKgYi3TgYLH5hnGfPE/U1dg6IfZ50UsIlLkwSA==" }, "chalk": { "version": "4.1.0", @@ -11700,17 +11691,20 @@ } }, "cloudinary": { - "version": "1.32.0", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-1.40.0.tgz", + "integrity": "sha512-Fifkl8NRw/M+Enw4cKCXc6e0Or28c5y6RVGYS3OCLzT1W8EfBt416FURhLuuL/S4BCVv8bSilmnM746kCtth3g==", "requires": { - "cloudinary-core": "^2.10.2", - "core-js": "^3.6.5", + "cloudinary-core": "^2.13.0", + "core-js": "^3.30.1", "lodash": "^4.17.21", - "proxy-agent": "^5.0.0", "q": "^1.5.1" } }, "cloudinary-core": { - "version": "2.11.3", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/cloudinary-core/-/cloudinary-core-2.13.0.tgz", + "integrity": "sha512-Nt0Q5I2FtenmJghtC4YZ3MZZbGg1wLm84SsxcuVwZ83OyJqG9CNIGp86CiI6iDv3QobaqBUpOT7vg+HqY5HxEA==", "requires": {} }, "co": { @@ -11791,11 +11785,15 @@ "version": "1.0.6" }, "cookiejar": { - "version": "2.1.3", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true }, "core-js": { - "version": "3.6.5" + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.32.1.tgz", + "integrity": "sha512-lqufgNn9NLnESg5mQeYsxQP5w7wrViSj0jr/kv6ECQiByzQkrn1MKvV0L3acttpDqfQrHLwr2KCMgX5b8X+lyQ==" }, "core-js-compat": { "version": "3.26.1", @@ -11829,10 +11827,6 @@ "css-what": { "version": "6.1.0" }, - "data-uri-to-buffer": { - "version": "3.0.1", - "optional": true - }, "debug": { "version": "3.2.7", "dev": true, @@ -11846,22 +11840,12 @@ }, "deep-is": { "version": "0.1.3", - "devOptional": true + "dev": true }, "deepmerge": { "version": "4.2.2", "dev": true }, - "degenerator": { - "version": "3.0.2", - "optional": true, - "requires": { - "ast-types": "^0.13.2", - "escodegen": "^1.8.1", - "esprima": "^4.0.0", - "vm2": "^3.9.8" - } - }, "delayed-stream": { "version": "1.0.0", "dev": true @@ -11980,23 +11964,6 @@ "escape-string-regexp": { "version": "1.0.5" }, - "escodegen": { - "version": "1.14.3", - "optional": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "estraverse": { - "version": "4.3.0", - "optional": true - } - } - }, "eslint": { "version": "8.29.0", "dev": true, @@ -12159,7 +12126,7 @@ }, "esprima": { "version": "4.0.1", - "devOptional": true + "dev": true }, "esquery": { "version": "1.4.0", @@ -12181,7 +12148,7 @@ }, "esutils": { "version": "2.0.3", - "devOptional": true + "dev": true }, "etag": { "version": "1.8.1" @@ -12345,14 +12312,16 @@ }, "fast-levenshtein": { "version": "2.0.6", - "devOptional": true + "dev": true }, "fast-safe-stringify": { "version": "2.1.1", "dev": true }, "fast-xml-parser": { - "version": "4.0.11", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", "optional": true, "requires": { "strnum": "^1.0.5" @@ -12379,10 +12348,6 @@ "flat-cache": "^3.0.4" } }, - "file-uri-to-path": { - "version": "2.0.0", - "optional": true - }, "fill-range": { "version": "7.0.1", "requires": { @@ -12463,15 +12428,6 @@ "fresh": { "version": "0.5.2" }, - "fs-extra": { - "version": "8.1.0", - "optional": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, "fs-minipass": { "version": "2.1.0", "requires": { @@ -12489,34 +12445,6 @@ "fs.realpath": { "version": "1.0.0" }, - "ftp": { - "version": "0.3.10", - "optional": true, - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "optional": true - }, - "readable-stream": { - "version": "1.1.14", - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "optional": true - } - } - }, "function-bind": { "version": "1.1.1" }, @@ -12561,27 +12489,6 @@ "version": "6.0.1", "dev": true }, - "get-uri": { - "version": "3.0.2", - "optional": true, - "requires": { - "@tootallnate/once": "1", - "data-uri-to-buffer": "3", - "debug": "4", - "file-uri-to-path": "2", - "fs-extra": "^8.1.0", - "ftp": "^0.3.10" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "optional": true, - "requires": { - "ms": "2.1.2" - } - } - } - }, "glob": { "version": "7.1.6", "requires": { @@ -12665,24 +12572,6 @@ "toidentifier": "1.0.1" } }, - "http-proxy-agent": { - "version": "4.0.1", - "optional": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "optional": true, - "requires": { - "ms": "2.1.2" - } - } - } - }, "http-status-codes": { "version": "2.2.0" }, @@ -12712,7 +12601,9 @@ } }, "ieee754": { - "version": "1.2.1" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { "version": "5.2.1", @@ -12759,8 +12650,9 @@ "version": "2.0.4" }, "ip": { - "version": "1.1.8", - "optional": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" }, "ipaddr.js": { "version": "1.9.1" @@ -12835,7 +12727,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -13203,7 +13097,9 @@ }, "dependencies": { "semver": { - "version": "7.3.8", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -13310,14 +13206,9 @@ "dev": true }, "json5": { - "version": "2.2.1" - }, - "jsonfile": { - "version": "4.0.0", - "optional": true, - "requires": { - "graceful-fs": "^4.1.6" - } + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" }, "jsonwebtoken": { "version": "9.0.0", @@ -13331,9 +13222,9 @@ }, "dependencies": { "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -13356,7 +13247,9 @@ } }, "kareem": { - "version": "2.5.0" + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==" }, "kleur": { "version": "3.0.3", @@ -13427,7 +13320,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -13527,6 +13422,8 @@ }, "mongodb-connection-string-url": { "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", "requires": { "@types/whatwg-url": "^8.2.1", "whatwg-url": "^11.0.0" @@ -13534,15 +13431,21 @@ "dependencies": { "tr46": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", "requires": { "punycode": "^2.1.1" } }, "webidl-conversions": { - "version": "7.0.0" + "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": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "requires": { "tr46": "^3.0.0", "webidl-conversions": "^7.0.0" @@ -13551,11 +13454,13 @@ } }, "mongoose": { - "version": "6.8.0", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.12.0.tgz", + "integrity": "sha512-sd/q83C6TBRPBrrD2A/POSbA/exbCFM2WOuY7Lf2JuIJFlHFG39zYSDTTAEiYlzIfahNOLmXPxBGFxdAch41Mw==", "requires": { - "bson": "^4.7.0", - "kareem": "2.5.0", - "mongodb": "4.12.1", + "bson": "^4.7.2", + "kareem": "2.5.1", + "mongodb": "4.17.1", "mpath": "0.9.0", "mquery": "4.0.3", "ms": "2.1.3", @@ -13563,18 +13468,22 @@ }, "dependencies": { "bson": { - "version": "4.7.0", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz", + "integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==", "requires": { "buffer": "^5.6.0" } }, "mongodb": { - "version": "4.12.1", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.17.1.tgz", + "integrity": "sha512-MBuyYiPUPRTqfH2dV0ya4dcr2E5N52ocBuZ8Sgg/M030nGF78v855B3Z27mZJnp8PxjnUquEnAtjOsphgMZOlQ==", "requires": { "@aws-sdk/credential-providers": "^3.186.0", - "bson": "^4.7.0", - "mongodb-connection-string-url": "^2.5.4", - "saslprep": "^1.0.3", + "@mongodb-js/saslprep": "^1.1.0", + "bson": "^4.7.2", + "mongodb-connection-string-url": "^2.6.0", "socks": "^2.7.1" } }, @@ -13650,10 +13559,6 @@ "neo-async": { "version": "2.6.2" }, - "netmask": { - "version": "2.0.2", - "optional": true - }, "node-addon-api": { "version": "5.0.0" }, @@ -13680,7 +13585,9 @@ } }, "nodemon": { - "version": "2.0.20", + "version": "2.0.22", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", + "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", "dev": true, "requires": { "chokidar": "^3.5.2", @@ -13787,39 +13694,6 @@ "optional-require": { "version": "1.0.3" }, - "optionator": { - "version": "0.8.3", - "optional": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "dependencies": { - "levn": { - "version": "0.3.0", - "optional": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "prelude-ls": { - "version": "1.1.2", - "optional": true - }, - "type-check": { - "version": "0.3.2", - "optional": true, - "requires": { - "prelude-ls": "~1.1.2" - } - } - } - }, "p-limit": { "version": "3.1.0", "dev": true, @@ -13847,39 +13721,6 @@ "version": "2.2.0", "dev": true }, - "pac-proxy-agent": { - "version": "5.0.0", - "optional": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4", - "get-uri": "3", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "5", - "pac-resolver": "^5.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "5" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "optional": true, - "requires": { - "ms": "2.1.2" - } - } - } - }, - "pac-resolver": { - "version": "5.0.1", - "optional": true, - "requires": { - "degenerator": "^3.0.2", - "ip": "^1.1.5", - "netmask": "^2.0.2" - } - }, "parent-module": { "version": "1.0.1", "dev": true, @@ -13992,44 +13833,6 @@ "ipaddr.js": "1.9.1" } }, - "proxy-agent": { - "version": "5.0.0", - "optional": true, - "requires": { - "agent-base": "^6.0.0", - "debug": "4", - "http-proxy-agent": "^4.0.0", - "https-proxy-agent": "^5.0.0", - "lru-cache": "^5.1.1", - "pac-proxy-agent": "^5.0.0", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^5.0.0" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "optional": true, - "requires": { - "ms": "2.1.2" - } - }, - "lru-cache": { - "version": "5.1.1", - "optional": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "yallist": { - "version": "3.1.1", - "optional": true - } - } - }, - "proxy-from-env": { - "version": "1.1.0", - "optional": true - }, "pstree.remy": { "version": "1.1.8", "dev": true @@ -14209,7 +14012,9 @@ } }, "semver": { - "version": "5.7.1", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true }, "send": { @@ -14293,7 +14098,9 @@ "version": "3.0.7" }, "simple-update-notifier": { - "version": "1.0.7", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", "dev": true, "requires": { "semver": "~7.0.0" @@ -14313,36 +14120,17 @@ "version": "3.0.0" }, "smart-buffer": { - "version": "4.2.0" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" }, "socks": { "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "requires": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" - }, - "dependencies": { - "ip": { - "version": "2.0.0" - } - } - }, - "socks-proxy-agent": { - "version": "5.0.1", - "optional": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "4", - "socks": "^2.3.3" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "optional": true, - "requires": { - "ms": "2.1.2" - } - } } }, "source-map": { @@ -14426,6 +14214,8 @@ }, "strnum": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", "optional": true }, "superagent": { @@ -14456,7 +14246,9 @@ "dev": true }, "semver": { - "version": "7.3.8", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -14547,7 +14339,9 @@ "version": "0.0.3" }, "tslib": { - "version": "2.4.1", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "devOptional": true }, "twostep": { @@ -14618,10 +14412,6 @@ "version": "2.1.0", "dev": true }, - "universalify": { - "version": "0.1.2", - "optional": true - }, "unpipe": { "version": "1.0.0" }, @@ -14647,6 +14437,8 @@ }, "uuid": { "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "optional": true }, "v8-to-istanbul": { @@ -14664,16 +14456,6 @@ "vary": { "version": "1.1.2" }, - "vm2": { - "version": "3.9.17", - "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.17.tgz", - "integrity": "sha512-AqwtCnZ/ERcX+AVj9vUsphY56YANXxRuqMb7GsDtAr0m0PcQX3u0Aj3KWiXM0YAHy7i6JEeHrwOnwXbGYgRpAw==", - "optional": true, - "requires": { - "acorn": "^8.7.0", - "acorn-walk": "^8.2.0" - } - }, "walker": { "version": "1.0.8", "dev": true, @@ -14705,8 +14487,10 @@ } }, "word-wrap": { - "version": "1.2.3", - "devOptional": true + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true }, "wordwrap": { "version": "1.0.0" @@ -14751,10 +14535,6 @@ "signal-exit": "^3.0.7" } }, - "xregexp": { - "version": "2.0.0", - "optional": true - }, "xtend": { "version": "4.0.2" }, From b1939335612472487cb62dae9f6654c58fcf4d07 Mon Sep 17 00:00:00 2001 From: dsantosferreira Date: Sun, 10 Sep 2023 20:22:54 +0100 Subject: [PATCH 27/30] Improved applications' endpoints documentation --- documentation/docs/applications/approve.md | 1 + documentation/docs/applications/create.md | 12 ++++++++---- documentation/docs/applications/reject.md | 1 + documentation/docs/applications/search.md | 2 +- documentation/docs/companies/get-application.md | 4 ++-- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/documentation/docs/applications/approve.md b/documentation/docs/applications/approve.md index 4a530069..160f2510 100644 --- a/documentation/docs/applications/approve.md +++ b/documentation/docs/applications/approve.md @@ -170,6 +170,7 @@ values={[ + ### Example 5 - Application is not verified **Code** : 409 CONFLICT diff --git a/documentation/docs/applications/create.md b/documentation/docs/applications/create.md index cc0786e4..953d12d8 100644 --- a/documentation/docs/applications/create.md +++ b/documentation/docs/applications/create.md @@ -13,8 +13,8 @@ import Highlight from "../../src/highlight.js" ## Details This endpoint is used to create company applications. -In order of a Company to use its account, the company must verify its application by clicking in a link sent by email after the creation of the application and then the Company should -finish its registration. +In order for a Company to use its account, the company must verify its application by clicking in a link sent +by email after its creation. After that the Company should finish its registration. **URL** : `/apply/company` @@ -36,7 +36,11 @@ see [register](../auth/register). Email used for the company application and subsequent account. Must be in a valid email format. -Can't already be in use for accounts or other applications. +Can't already be in use on any account. + +:::info +After creating an application, if another application is created with the same email after 10 minutes, the existing one will be replaced. Creating the new application before the 10 minute mark will result in an error. +::: ### password @@ -181,7 +185,7 @@ values={[ "password": "password123", "companyName": "Company", "motivation": "We wish to revolutionize the industry with young engineers." -} +}ara quem usa o timetable-bruteforcer ``` diff --git a/documentation/docs/applications/reject.md b/documentation/docs/applications/reject.md index 2a889402..1ef7a3a9 100644 --- a/documentation/docs/applications/reject.md +++ b/documentation/docs/applications/reject.md @@ -197,6 +197,7 @@ values={[ + ### Example 5 - Application is not verified **Code** : 409 CONFLICT diff --git a/documentation/docs/applications/search.md b/documentation/docs/applications/search.md index a96a6171..574f52f2 100644 --- a/documentation/docs/applications/search.md +++ b/documentation/docs/applications/search.md @@ -188,7 +188,7 @@ values={[ "submittedAt": "2022-09-07T13:15:15.971Z", "isVerified": false, "__v": 0, - "state": "PENDING" + "state": "UNVERIFIED" } ], "docCount": 4 diff --git a/documentation/docs/companies/get-application.md b/documentation/docs/companies/get-application.md index c1dbccdf..165c4082 100644 --- a/documentation/docs/companies/get-application.md +++ b/documentation/docs/companies/get-application.md @@ -77,7 +77,7 @@ values={[ ### Example 2 - Insufficient permission -**Code** : 401 UNAUTHORIZED +**Code** : 401 UNAUTHORIZED 422 UNPROCESSABLE ENTITY +**Code** : 422 UNPROCESSABLE ENTITY Date: Wed, 18 Oct 2023 14:00:40 +0100 Subject: [PATCH 28/30] Fixed netlify issue --- documentation/package-lock.json | 2822 ++++--------------------------- documentation/package.json | 2 +- 2 files changed, 331 insertions(+), 2493 deletions(-) diff --git a/documentation/package-lock.json b/documentation/package-lock.json index a52f01dc..cd042848 100644 --- a/documentation/package-lock.json +++ b/documentation/package-lock.json @@ -96,7 +96,7 @@ "@algolia/transporter": "4.8.4" } }, - "node_modules/@algolia/logger-common": { + "@algolia/logger-common": { "version": "4.8.4", "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.8.4.tgz", "integrity": "sha512-6hOaFG75Onmant9adcaeCZgvPYfnif7n0H1ycbixm6/WH3SmxqPMG+CMiW8mTNTRrrAEceQVrq6tDHD8jdnOOw==" @@ -182,15 +182,7 @@ } } }, - "node_modules/@babel/core/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@babel/generator": { + "@babel/generator": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==", @@ -235,15 +227,7 @@ } } }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { + "@babel/helper-create-class-features-plugin": { "version": "7.12.1", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz", "integrity": "sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==", @@ -1003,15 +987,7 @@ } } }, - "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { + "@babel/plugin-transform-shorthand-properties": { "version": "7.12.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz", "integrity": "sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw==", @@ -1159,15 +1135,7 @@ } } }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@babel/preset-modules": { + "@babel/preset-modules": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", @@ -1437,20 +1405,7 @@ } } }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-docs": { + "@docusaurus/plugin-content-docs": { "version": "2.0.0-alpha.70", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-alpha.70.tgz", "integrity": "sha512-LZre12Q0sxLgi2XgjQbNQMV+jFG7v0+8hRzgBL+iCRiLCa4NlV7+M6mEHJGJJXSKqbfH7CelaUOESqEgPpVQXQ==", @@ -1542,72 +1497,7 @@ } } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/p-finally": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", - "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@docusaurus/plugin-content-pages": { + "@docusaurus/plugin-content-pages": { "version": "2.0.0-alpha.70", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-alpha.70.tgz", "integrity": "sha512-HiFa5l1RDs155ATyYKkPtyIs/d6WJgSAyVfY5ji0Bsixp/K/Kh9YUZYMeTfeMIdhGYe3AAJz+PSZHYRpwTo1wA==", @@ -1647,20 +1537,7 @@ } } }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/@docusaurus/plugin-debug": { + "@docusaurus/plugin-debug": { "version": "2.0.0-alpha.70", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-alpha.70.tgz", "integrity": "sha512-h/x5KtS/YJerhY6C6sJOaP9gMaSVnjj1qZ6r9E/IFujQJ7bSKnk1unqBQpVXADkQhP081ENPL01ubc0/JbE1Mw==", @@ -1843,7 +1720,7 @@ "@hapi/hoek": "^9.0.0" } }, - "node_modules/@mdx-js/mdx": { + "@mdx-js/mdx": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", @@ -1899,15 +1776,7 @@ } } }, - "node_modules/@mdx-js/mdx/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@mdx-js/react": { + "@mdx-js/react": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==" @@ -2501,24 +2370,19 @@ "@algolia/transporter": "4.8.4" } }, - "node_modules/algoliasearch-helper": { + "algoliasearch-helper": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.3.4.tgz", "integrity": "sha512-1Ts2XcgGdjGlDrp3v6zbY8VW+X9+jJ5rBmtPBmXOQLd4b5t/LpJlaBdxoAnlMfVFjywP7KSAdmyFUNNYVHDyRQ==", - "deprecated": "3.7.3", - "dependencies": { + "requires": { "events": "^1.1.1" }, - "peerDependencies": { - "algoliasearch": ">= 3.1 < 5" - } - }, - "node_modules/algoliasearch-helper/node_modules/events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "engines": { - "node": ">=0.4.x" + "dependencies": { + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + } } }, "alphanum-sort": { @@ -2571,26 +2435,12 @@ "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=" }, - "node_modules/ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { + "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "engines": { - "node": ">=6" - } + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, - "node_modules/ansi-styles": { + "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==", @@ -2712,11 +2562,11 @@ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, - "node_modules/async": { + "async": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dependencies": { + "requires": { "lodash": "^4.17.14" } }, @@ -2754,11 +2604,11 @@ "postcss-value-parser": "^4.1.0" } }, - "node_modules/axios": { + "axios": { "version": "0.21.1", "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", - "dependencies": { + "requires": { "follow-redirects": "^1.10.0" } }, @@ -2845,20 +2695,7 @@ } } }, - "node_modules/babel-loader/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/babel-plugin-apply-mdx-type-prop": { + "babel-plugin-apply-mdx-type-prop": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz", "integrity": "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==", @@ -2979,7 +2816,7 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, - "node_modules/bluebird": { + "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" @@ -3132,29 +2969,19 @@ "pako": "~1.0.5" } }, - "node_modules/browserslist": { + "browserslist": { "version": "4.16.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.1.tgz", "integrity": "sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==", - "dependencies": { + "requires": { "caniuse-lite": "^1.0.30001173", "colorette": "^1.2.1", "electron-to-chromium": "^1.3.634", "escalade": "^3.1.1", "node-releases": "^1.1.69" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" } }, - "node_modules/buffer": { + "buffer": { "version": "4.9.2", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", @@ -3269,20 +3096,7 @@ } } }, - "node_modules/cache-loader/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/cacheable-request": { + "cacheable-request": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", @@ -3316,23 +3130,7 @@ } } }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind": { + "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", @@ -3404,7 +3202,7 @@ "lodash.uniq": "^4.5.0" } }, - "node_modules/caniuse-lite": { + "caniuse-lite": { "version": "1.0.30001181", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001181.tgz", "integrity": "sha512-m5ul/ARCX50JB8BSNM+oiPmQrR5UmngaQ3QThTTp5HcIIQGP/nPBs82BYLE+tigzm3VW+F4BJIhUyaVtEweelQ==" @@ -3488,7 +3286,7 @@ "version": "0.22.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", - "dependencies": { + "requires": { "css-select": "~1.2.0", "dom-serializer": "~0.1.0", "entities": "~1.1.1", @@ -3506,14 +3304,6 @@ "lodash.reject": "^4.4.0", "lodash.some": "^4.4.0" }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cheerio/node_modules/css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", "dependencies": { "css-select": { "version": "1.2.0", @@ -3680,18 +3470,7 @@ "tiny-emitter": "^2.0.0" } }, - "node_modules/clipboard": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz", - "integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==", - "optional": true, - "dependencies": { - "good-listener": "^1.2.2", - "select": "^1.1.2", - "tiny-emitter": "^2.0.0" - } - }, - "node_modules/cliui": { + "cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", @@ -3784,11 +3563,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "node_modules/color-string": { + "color-string": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz", "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==", - "dependencies": { + "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } @@ -4040,11 +3819,11 @@ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" }, - "node_modules/core-js-compat": { + "core-js-compat": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.3.tgz", "integrity": "sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog==", - "dependencies": { + "requires": { "browserslist": "^4.16.1", "semver": "7.0.0" }, @@ -4056,15 +3835,7 @@ } } }, - "node_modules/core-js-compat/node_modules/semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/core-js-pure": { + "core-js-pure": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.8.3.tgz", "integrity": "sha512-V5qQZVAr9K0xu7jXg1M7qTEwuxUgqr7dUOezGaNa7i+Xn9oXAU/d1fzqD9ObuwpVQOaorO5s70ckyi1woP9lVA==" @@ -4290,20 +4061,7 @@ } } }, - "node_modules/css-loader/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/css-prefers-color-scheme": { + "css-prefers-color-scheme": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz", "integrity": "sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==", @@ -4650,13 +4408,13 @@ } } }, - "node_modules/delegate": { + "delegate": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", "optional": true }, - "node_modules/depd": { + "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" @@ -4737,11 +4495,11 @@ "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" }, - "node_modules/dns-packet": { + "dns-packet": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", - "dependencies": { + "requires": { "ip": "^1.1.0", "safe-buffer": "^5.0.1" } @@ -4877,16 +4635,16 @@ "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" }, - "node_modules/electron-to-chromium": { + "electron-to-chromium": { "version": "1.3.649", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.649.tgz", "integrity": "sha512-ojGDupQ3UMkvPWcTICe4JYe17+o9OLiFMPoduoR72Zp2ILt1mRVeqnxBEd6s/ptekrnsFU+0A4lStfBe/wyG/A==" }, - "node_modules/elliptic": { + "elliptic": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", - "dependencies": { + "requires": { "bn.js": "^4.4.0", "brorand": "^1.0.1", "hash.js": "^1.0.0", @@ -4894,6 +4652,13 @@ "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } } }, "emoji-regex": { @@ -5085,16 +4850,10 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, - "node_modules/eta": { + "eta": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/eta/-/eta-1.12.1.tgz", - "integrity": "sha512-H8npoci2J/7XiPnVcCVulBSPsTNGvGaINyMjQDU8AFqp9LGsEYS88g2CiU+d01Sg44WtX7o4nb8wUJ9vnI+tiA==", - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "url": "https://github.com/eta-dev/eta?sponsor=1" - } + "integrity": "sha512-H8npoci2J/7XiPnVcCVulBSPsTNGvGaINyMjQDU8AFqp9LGsEYS88g2CiU+d01Sg44WtX7o4nb8wUJ9vnI+tiA==" }, "etag": { "version": "1.8.1", @@ -5127,18 +4886,7 @@ "original": "^1.0.0" } }, - "node_modules/eventsource": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", - "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", - "dependencies": { - "original": "^1.0.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/evp_bytestokey": { + "evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", @@ -5206,53 +4954,7 @@ } } }, - "node_modules/execa/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "engines": { - "node": ">=4" - } - }, - "node_modules/execa/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/execa/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/expand-brackets": { + "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", @@ -5731,7 +5433,7 @@ } } }, - "node_modules/filesize": { + "filesize": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.0.1.tgz", "integrity": "sha512-u4AYWPgbI5GBhs6id1KdImZWn5yfyFrrQ8OWZdN7ZMfA8Bf4HcO0BGo9bmUIEV8yrp8I1xVfJ/dn90GtFNNJcg==" @@ -5810,24 +5512,10 @@ "fbjs": "^3.0.0" } }, - "node_modules/follow-redirects": { + "follow-redirects": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz", - "integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } + "integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA==" }, "for-in": { "version": "1.0.2", @@ -5980,144 +5668,7 @@ } } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fragment-cache": { + "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", @@ -6299,11 +5850,11 @@ "path-is-absolute": "^1.0.0" } }, - "node_modules/glob-parent": { + "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dependencies": { + "requires": { "is-glob": "^4.0.1" } }, @@ -6375,16 +5926,16 @@ "slash": "^3.0.0" } }, - "node_modules/good-listener": { + "good-listener": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", "optional": true, - "dependencies": { + "requires": { "delegate": "^3.1.2" } }, - "node_modules/got": { + "got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", @@ -6714,12 +6265,12 @@ "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=" }, - "node_modules/html-comment-regex": { + "html-comment-regex": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==" }, - "node_modules/html-entities": { + "html-entities": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==" @@ -6793,29 +6344,7 @@ } } }, - "node_modules/html-webpack-plugin/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/html-webpack-plugin/node_modules/util.promisify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", - "dependencies": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" - } - }, - "node_modules/htmlparser2": { + "htmlparser2": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", @@ -7187,22 +6716,6 @@ "strip-ansi": "^6.0.0", "through": "^2.3.6" }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/inquirer/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { "ansi-regex": { "version": "5.0.0", @@ -7584,18 +7097,7 @@ "html-comment-regex": "^1.1.0" } }, - "node_modules/is-svg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", - "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", - "dependencies": { - "html-comment-regex": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-symbol": { + "is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", @@ -7796,11 +7298,11 @@ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==" }, - "node_modules/loader-utils": { + "loader-utils": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", - "dependencies": { + "requires": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", "json5": "^2.1.2" @@ -7814,7 +7316,7 @@ "p-locate": "^4.1.0" } }, - "node_modules/lodash": { + "lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" @@ -8274,47 +7776,7 @@ } } }, - "node_modules/mini-css-extract-plugin/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mini-css-extract-plugin/node_modules/normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dependencies": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/minimalistic-assert": { + "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" @@ -8469,7 +7931,7 @@ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, - "node_modules/nanomatch": { + "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", @@ -8686,33 +8148,7 @@ } } }, - "node_modules/null-loader/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/null-loader/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/num2fraction": { + "num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" @@ -8881,15 +8317,15 @@ "last-call-webpack-plugin": "^3.0.0" } }, - "node_modules/original": { + "original": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", - "dependencies": { + "requires": { "url-parse": "^1.4.3" } }, - "node_modules/os-browserify": { + "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" @@ -9108,7 +8544,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, - "node_modules/path-parse": { + "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" @@ -9135,7 +8571,7 @@ "sha.js": "^2.4.8" } }, - "node_modules/picomatch": { + "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" @@ -9239,21 +8675,49 @@ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, - "node_modules/postcss": { + "postcss": { "version": "7.0.35", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", - "dependencies": { + "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", "supports-color": "^6.1.0" }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss-attribute-case-insensitive": { @@ -9653,33 +9117,7 @@ } } }, - "node_modules/postcss-loader/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/postcss-loader/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/postcss-logical": { + "postcss-logical": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz", "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==", @@ -10227,11 +9665,11 @@ "sort-css-media-queries": "1.5.0" } }, - "node_modules/postcss-svgo": { + "postcss-svgo": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", - "dependencies": { + "requires": { "is-svg": "^3.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0", @@ -10280,50 +9718,7 @@ "uniqs": "^2.0.0" } }, - "node_modules/postcss/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss/node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/prepend-http": { + "prepend-http": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" @@ -10355,15 +9750,7 @@ "clipboard": "^2.0.0" } }, - "node_modules/prismjs": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz", - "integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==", - "optionalDependencies": { - "clipboard": "^2.0.0" - } - }, - "node_modules/process": { + "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" @@ -10929,523 +10316,113 @@ } } }, - "node_modules/react-dev-utils/node_modules/@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/react-dev-utils/node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" + "react-dom": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" } }, - "node_modules/react-dev-utils/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } + "react-error-overlay": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.8.tgz", + "integrity": "sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw==" }, - "node_modules/react-dev-utils/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } + "react-fast-compare": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", + "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" }, - "node_modules/react-dev-utils/node_modules/browserslist": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.10.0.tgz", - "integrity": "sha512-TpfK0TDgv71dzuTsEAlQiHeWQ/tiPqgNZVdv046fvNtBZrjbv2O3TsWCDU0AWGJJKCF/KsjNdLzR9hXOsh/CfA==", - "dependencies": { - "caniuse-lite": "^1.0.30001035", - "electron-to-chromium": "^1.3.378", - "node-releases": "^1.1.52", - "pkg-up": "^3.1.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "funding": { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" + "react-helmet": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", + "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==", + "requires": { + "object-assign": "^4.1.1", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.1.1", + "react-side-effect": "^2.1.0" } }, - "node_modules/react-dev-utils/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "node_modules/react-dev-utils/node_modules/chalk/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "engines": { - "node": ">=0.8.0" + "react-json-view": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/react-json-view/-/react-json-view-1.20.4.tgz", + "integrity": "sha512-QBhb1STnWif+wY8Bsl+ISyDnKTocN/37gSauq8MNHjvu7UOLmdTAgynnC5/rrPh1sAdakg7oIhxU0l660xQg+Q==", + "requires": { + "flux": "^4.0.1", + "react-base16-styling": "^0.6.0", + "react-lifecycles-compat": "^3.0.4", + "react-textarea-autosize": "^6.1.0" } }, - "node_modules/react-dev-utils/node_modules/cli-width": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==" + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, - "node_modules/react-dev-utils/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" + "react-loadable": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-loadable/-/react-loadable-5.5.0.tgz", + "integrity": "sha512-C8Aui0ZpMd4KokxRdVAm2bQtI03k2RMRNzOB+IipV3yxFTSVICv7WoUr5L9ALB5BmKO1iHgZtWM8EvYG83otdg==", + "requires": { + "prop-types": "^15.5.0" } }, - "node_modules/react-dev-utils/node_modules/detect-port-alt": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", - "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", - "dependencies": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, - "bin": { - "detect": "bin/detect-port", - "detect-port": "bin/detect-port" - }, - "engines": { - "node": ">= 4.2.1" + "react-loadable-ssr-addon": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon/-/react-loadable-ssr-addon-0.3.0.tgz", + "integrity": "sha512-E+lnmDakV0k6ut6R2J77vurwCOwTKEwKlHs9S62G8ez+ujecLPcqjt3YAU8M58kIGjp2QjFlZ7F9QWkq/mr6Iw==", + "requires": { + "@babel/runtime": "^7.10.3" } }, - "node_modules/react-dev-utils/node_modules/dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", - "dependencies": { - "arrify": "^1.0.1", - "path-type": "^3.0.0" + "react-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", + "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/react-dev-utils/node_modules/emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "engines": { - "node": ">= 0.10" + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + } } }, - "node_modules/react-dev-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/react-dev-utils/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dev-utils/node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dev-utils/node_modules/fast-glob": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", - "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", - "dependencies": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/react-dev-utils/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dev-utils/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dev-utils/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/react-dev-utils/node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dev-utils/node_modules/globby": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", - "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", - "dependencies": { - "array-union": "^1.0.1", - "dir-glob": "2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/react-dev-utils/node_modules/ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" - }, - "node_modules/react-dev-utils/node_modules/inquirer": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.4.tgz", - "integrity": "sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ==", - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^2.4.2", - "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.15", - "mute-stream": "0.0.8", - "run-async": "^2.2.0", - "rxjs": "^6.5.3", - "string-width": "^4.1.0", - "strip-ansi": "^5.1.0", - "through": "^2.3.6" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/react-dev-utils/node_modules/inquirer/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/react-dev-utils/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dev-utils/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dev-utils/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/react-dev-utils/node_modules/loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/react-dev-utils/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dev-utils/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/react-dev-utils/node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/react-dev-utils/node_modules/slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dev-utils/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-dev-utils/node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/react-dev-utils/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - } - }, - "react-error-overlay": { - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.8.tgz", - "integrity": "sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw==" - }, - "react-fast-compare": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", - "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" - }, - "react-helmet": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", - "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==", - "requires": { - "object-assign": "^4.1.1", - "prop-types": "^15.7.2", - "react-fast-compare": "^3.1.1", - "react-side-effect": "^2.1.0" - } - }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "react-json-view": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/react-json-view/-/react-json-view-1.20.4.tgz", - "integrity": "sha512-QBhb1STnWif+wY8Bsl+ISyDnKTocN/37gSauq8MNHjvu7UOLmdTAgynnC5/rrPh1sAdakg7oIhxU0l660xQg+Q==", - "requires": { - "flux": "^4.0.1", - "react-base16-styling": "^0.6.0", - "react-lifecycles-compat": "^3.0.4", - "react-textarea-autosize": "^6.1.0" - } - }, - "react-lifecycles-compat": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" - }, - "react-loadable": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/react-loadable/-/react-loadable-5.5.0.tgz", - "integrity": "sha512-C8Aui0ZpMd4KokxRdVAm2bQtI03k2RMRNzOB+IipV3yxFTSVICv7WoUr5L9ALB5BmKO1iHgZtWM8EvYG83otdg==", - "requires": { - "prop-types": "^15.5.0" - } - }, - "react-loadable-ssr-addon": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon/-/react-loadable-ssr-addon-0.3.0.tgz", - "integrity": "sha512-E+lnmDakV0k6ut6R2J77vurwCOwTKEwKlHs9S62G8ez+ujecLPcqjt3YAU8M58kIGjp2QjFlZ7F9QWkq/mr6Iw==", - "requires": { - "@babel/runtime": "^7.10.3" - } - }, - "react-router": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", - "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", - "requires": { - "@babel/runtime": "^7.1.2", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "mini-create-react-context": "^0.4.0", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "requires": { - "isarray": "0.0.1" - } - } - } - }, - "react-router-config": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", - "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", - "requires": { - "@babel/runtime": "^7.1.2" + "react-router-config": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", + "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", + "requires": { + "@babel/runtime": "^7.1.2" } }, "react-router-dom": { @@ -11768,15 +10745,7 @@ } } }, - "node_modules/remark-mdx/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/remark-parse": { + "remark-parse": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", @@ -11812,38 +10781,34 @@ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, - "node_modules/renderkid": { + "renderkid": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.5.tgz", "integrity": "sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ==", - "dependencies": { + "requires": { "css-select": "^2.0.2", "dom-converter": "^0.2", "htmlparser2": "^3.10.1", "lodash": "^4.17.20", "strip-ansi": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } } }, - "node_modules/renderkid/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/renderkid/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-element": { + "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" @@ -12055,32 +11020,29 @@ "kind-of": "^6.0.0" } }, - "node_modules/select": { + "select": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=", "optional": true }, - "node_modules/select-hose": { + "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" }, - "node_modules/selfsigned": { + "selfsigned": { "version": "1.10.8", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", - "dependencies": { + "requires": { "node-forge": "^0.10.0" } }, - "node_modules/semver": { + "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, "semver-diff": { "version": "3.1.1", @@ -12098,11 +11060,11 @@ "randombytes": "^2.1.0" } }, - "node_modules/serve-handler": { + "serve-handler": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", - "dependencies": { + "requires": { "bytes": "3.0.0", "content-disposition": "0.5.2", "fast-url-parser": "1.1.3", @@ -12112,24 +11074,43 @@ "path-to-regexp": "2.2.1", "range-parser": "1.2.0" }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-handler/node_modules/path-to-regexp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", - "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" - }, - "node_modules/serve-handler/node_modules/range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "engines": { - "node": ">= 0.6" + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "~1.33.0" + } + }, + "path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + } } }, - "node_modules/serve-index": { + "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", @@ -12227,11 +11208,11 @@ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" }, - "node_modules/shelljs": { + "shelljs": { "version": "0.8.4", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", - "dependencies": { + "requires": { "glob": "^7.0.0", "interpret": "^1.0.0", "rechoir": "^0.6.2" @@ -12446,11 +11427,11 @@ "urix": "^0.1.0" } }, - "node_modules/source-map-support": { + "source-map-support": { "version": "0.5.19", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dependencies": { + "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" }, @@ -12676,35 +11657,6 @@ "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.0" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/string-width/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dependencies": { "ansi-regex": { "version": "5.0.0", @@ -12889,11 +11841,11 @@ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" }, - "node_modules/tar": { + "tar": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", - "dependencies": { + "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^3.0.0", @@ -12901,31 +11853,24 @@ "mkdirp": "^1.0.3", "yallist": "^4.0.0" }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } } }, - "node_modules/term-size": { + "term-size": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==" }, - "node_modules/terser": { + "terser": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "dependencies": { + "requires": { "commander": "^2.20.0", "source-map": "~0.6.1", "source-map-support": "~0.5.12" @@ -12958,26 +11903,6 @@ "terser": "^5.3.4", "webpack-sources": "^1.4.3" }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/terser-webpack-plugin/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/terser-webpack-plugin/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dependencies": { "commander": { "version": "2.20.3", @@ -13026,69 +11951,7 @@ } } }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", - "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", - "dependencies": { - "@types/json-schema": "^7.0.6", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/terser-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/terser-webpack-plugin/node_modules/terser": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz", - "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==", - "dependencies": { - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.19" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin/node_modules/terser/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/terser/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/text-table": { + "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" @@ -13149,13 +12012,13 @@ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" }, - "node_modules/tiny-emitter": { + "tiny-emitter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", "optional": true }, - "node_modules/tiny-invariant": { + "tiny-invariant": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" @@ -13262,8 +12125,7 @@ "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", - "deprecated": "Use String.prototype.trim() instead" + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" }, "trim-trailing-lines": { "version": "1.1.4", @@ -13549,7 +12411,7 @@ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" }, - "node_modules/update-notifier": { + "update-notifier": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", @@ -13620,28 +12482,11 @@ } } }, - "node_modules/url-loader/node_modules/schema-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", - "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", - "dependencies": { - "@types/json-schema": "^7.0.6", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/url-parse": { + "url-parse": { "version": "1.4.7", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", - "dependencies": { + "requires": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } @@ -14065,245 +12910,7 @@ } } }, - "node_modules/watchpack-chokidar2/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "optional": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", - "optional": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" - } - }, - "node_modules/watchpack-chokidar2/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "optional": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "optional": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "optional": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "optional": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "optional": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "optional": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "optional": true, - "dependencies": { - "binary-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "optional": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "optional": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "optional": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "optional": true, - "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/watchpack-chokidar2/node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/watchpack-chokidar2/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==", - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "optional": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wbuf": { + "wbuf": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", @@ -14710,29 +13317,19 @@ "range-parser": "^1.2.1", "webpack-log": "^2.0.0" }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/webpack-dev-middleware/node_modules/mime": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz", - "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" + "dependencies": { + "mime": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz", + "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==" + } } }, - "node_modules/webpack-dev-server": { + "webpack-dev-server": { "version": "3.11.2", "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz", "integrity": "sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ==", - "dependencies": { + "requires": { "ansi-html": "0.0.7", "bonjour": "^3.5.0", "chokidar": "^2.1.8", @@ -15087,429 +13684,30 @@ } } }, - "node_modules/webpack-dev-server/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/anymatch": { + "webpack-log": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" } }, - "node_modules/webpack-dev-server/node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" + "webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", + "requires": { + "lodash": "^4.17.15" } }, - "node_modules/webpack-dev-server/node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" - } - }, - "node_modules/webpack-dev-server/node_modules/del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dependencies": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack-dev-server/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/webpack-dev-server/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/webpack-dev-server/node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/globby/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/is-absolute-url": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", - "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-dev-server/node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dependencies": { - "binary-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack-dev-server/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack-dev-server/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "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/webpack-dev-server/node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/webpack-dev-server/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/webpack-dev-server/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/webpack-dev-server/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/webpack-dev-server/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack-dev-server/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", - "requires": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" - } - }, - "webpack-merge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", - "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", - "requires": { - "lodash": "^4.17.15" - } - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" }, "dependencies": { "source-map": { @@ -15519,348 +13717,7 @@ } } }, - "node_modules/webpack/node_modules/cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", - "dependencies": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "node_modules/webpack/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, - "node_modules/webpack/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "engines": { - "node": ">=4" - } - }, - "node_modules/webpack/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/webpack/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/webpack/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/webpack/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "engines": { - "node": ">=4" - } - }, - "node_modules/webpack/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack/node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/webpack/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/webpack/node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/webpack/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dependencies": { - "figgy-pudding": "^3.5.1" - } - }, - "node_modules/webpack/node_modules/terser-webpack-plugin": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", - "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", - "dependencies": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^4.0.0", - "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" - }, - "engines": { - "node": ">= 6.9.0" - }, - "peerDependencies": { - "webpack": "^4.0.0" - } - }, - "node_modules/webpack/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/webpackbar": { + "webpackbar": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-4.0.0.tgz", "integrity": "sha512-k1qRoSL/3BVuINzngj09nIwreD8wxV4grcuhHTD8VJgUbGcy8lQSPqv+bM00B7F+PffwIsQ8ISd4mIwRbr23eQ==", @@ -15874,25 +13731,6 @@ "text-table": "^0.2.0", "wrap-ansi": "^6.0.0" }, - "engines": { - "node": ">= 8.0.0" - }, - "peerDependencies": { - "webpack": "^3.0.0 || ^4.0.0" - } - }, - "node_modules/webpackbar/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/webpackbar/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { "ansi-regex": { "version": "5.0.0", @@ -16052,11 +13890,11 @@ "typedarray-to-buffer": "^3.1.5" } }, - "node_modules/ws": { + "ws": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dependencies": { + "requires": { "async-limiter": "~1.0.0" } }, @@ -16184,4 +14022,4 @@ "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==" } } -} \ No newline at end of file +} diff --git a/documentation/package.json b/documentation/package.json index 5938a896..6a91ec85 100644 --- a/documentation/package.json +++ b/documentation/package.json @@ -31,4 +31,4 @@ "last 1 safari version" ] } -} \ No newline at end of file +} From f7fd7e314b6dd100869f9164c26b0566e69676a7 Mon Sep 17 00:00:00 2001 From: Francisco Cardoso Date: Mon, 5 Feb 2024 22:34:50 +0000 Subject: [PATCH 29/30] When creating a new application if an old application exists the old one is updated instead of being deleted and replaced --- src/api/routes/application.js | 6 ++---- src/services/application.js | 10 ++++++++-- test/end-to-end/apply/company/:token/validate.js | 4 ++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/api/routes/application.js b/src/api/routes/application.js index efaf0508..a2acbf3b 100644 --- a/src/api/routes/application.js +++ b/src/api/routes/application.js @@ -17,9 +17,7 @@ export default (app) => { router.post("/", validators.create, applicationMiddleware.exceededCreationTimeLimit, async (req, res, next) => { try { const applicationService = new ApplicationService(); - await applicationService.deleteApplications(req.body.email); - // This is safe since the service is destructuring the passed object and the fields have been validated - const application = await applicationService.create(req.body); + const application = await applicationService.updateOrCreate({ email: req.body.email }, req.body); return res.json(application); } catch (err) { console.error(err); @@ -33,7 +31,7 @@ export default (app) => { router.post("/:token/validate", validators.finishValidation, validToken, async (req, res, next) => { const { _id: id } = req.locals.token; try { - await new ApplicationService().applicationValidation(id); + await new ApplicationService().validateApplication(id); return res.status(HTTPStatus.OK).json({}); } catch (err) { if (err instanceof CompanyApplicationAlreadyValidated) { diff --git a/src/services/application.js b/src/services/application.js index a471dcb1..5bb60d90 100644 --- a/src/services/application.js +++ b/src/services/application.js @@ -220,11 +220,11 @@ class CompanyApplicationService { return `${config.application_confirmation_link}${token}/validate`; } - async applicationValidation(id) { + async validateApplication(id) { const application = await this.findById(id); try { - application.companyValidation(); + application.verifyCompany(); await EmailService.sendMail({ to: config.mail_from, ...NEW_COMPANY_APPLICATION_ADMINS(application.email, application.companyName, application.motivation) @@ -248,6 +248,12 @@ class CompanyApplicationService { } } + async updateOrCreate(query, update) { + let application = await CompanyApplication.findOne(query); + if (!application) application = await this.create(update); + else application = await CompanyApplication.findOneAndUpdate(query, update, { new: true }); + return application; + } async deleteApplications(email) { await CompanyApplication.deleteMany({ email: email, isVerified: false }); } diff --git a/test/end-to-end/apply/company/:token/validate.js b/test/end-to-end/apply/company/:token/validate.js index 4633a7f4..fe6af34b 100644 --- a/test/end-to-end/apply/company/:token/validate.js +++ b/test/end-to-end/apply/company/:token/validate.js @@ -73,7 +73,7 @@ describe("POST /apply/company/:token/validate", () => { const companyEmailOptions = NEW_COMPANY_APPLICATION_COMPANY( application.companyName, - res.body._id + res.body.id ); expect(EmailService.sendMail).toHaveBeenNthCalledWith(2, expect.objectContaining({ @@ -127,7 +127,7 @@ describe("POST /apply/company/:token/validate", () => { Date.now = () => mockCurrentDate; await request() .post(`/apply/company/${generatedToken}/validate`) - .expect(StatusCodes.GONE); + .expect(StatusCodes.FORBIDDEN); Date.now = RealDateNow; }); From 46d86fdcdfb2f0e517db4c787b3c046ea0ca1f91 Mon Sep 17 00:00:00 2001 From: Francisco Cardoso Date: Mon, 5 Feb 2024 22:35:43 +0000 Subject: [PATCH 30/30] Updating email texts and error types --- src/api/middleware/auth.js | 2 +- .../approval_notification.handlebars | 9 ++++----- .../confirm-application.handlebars | 5 ++--- .../new_company_application_company.handlebars | 2 +- src/models/CompanyApplication.js | 2 +- src/services/account.js | 2 +- test/end-to-end/apply/company/index.js | 15 +++++++++++---- test/end-to-end/auth.js | 4 ++-- test/end-to-end/auth/recover/:token/confirm.js | 4 ++-- 9 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/api/middleware/auth.js b/src/api/middleware/auth.js index aed1656a..65cd2355 100644 --- a/src/api/middleware/auth.js +++ b/src/api/middleware/auth.js @@ -88,7 +88,7 @@ export const validToken = (req, res, next) => { return next(); } catch (jwtErr) { if (jwtErr.name === "TokenExpiredError") { - return next(new APIError(HTTPStatus.GONE, ErrorTypes.FORBIDDEN, ValidationReasons.EXPIRED_TOKEN)); + return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.EXPIRED_TOKEN)); } else { return next(new APIError(HTTPStatus.NOT_FOUND, ErrorTypes.FORBIDDEN, ValidationReasons.INVALID_TOKEN)); } diff --git a/src/email-templates/approval_notification.handlebars b/src/email-templates/approval_notification.handlebars index daf71e9a..cb4d8aa8 100644 --- a/src/email-templates/approval_notification.handlebars +++ b/src/email-templates/approval_notification.handlebars @@ -1,9 +1,8 @@

We are delighted to have you on board, {{companyName}}!

-

We are pleased to inform you that your application has been accepted, and all the offers - you have created so far are now visible to the public!

-

Going forward, any offer you create will be immediately visible to the public audience.

+

We are pleased to inform you that your application has been accepted, and all the offers you have created are now accessible to the public!

+

From now on, any offer you create will be immediately available to the public audience.


-

If you need anything else, don't hesitate to contact us at nijobs@aefeup.pt!

+

If you have any further questions, don't hesitate to contact us at nijobs@aefeup.pt!


Sincerely,

-

NIJobs team at NIAEFEUP

\ No newline at end of file +

NIJobs team at NIAEFEUP

diff --git a/src/email-templates/confirm-application.handlebars b/src/email-templates/confirm-application.handlebars index 8b55a041..4dae304b 100644 --- a/src/email-templates/confirm-application.handlebars +++ b/src/email-templates/confirm-application.handlebars @@ -1,7 +1,6 @@

Confirm your NIJobs application

We have received your application successfully!

-

To complete the process, please click on the following link. Kindly note that the link will expire in 10 minutes.

-
+

To complete the process, please click on this link. Kindly note that the link will expire in 10 minutes.


If you did not make this request or require any further assistance, please reach out to us at nijobs@aefeup.pt!


Sincerely,

-

NIJobs team at NIAEFEUP

\ No newline at end of file +

NIJobs team at NIAEFEUP

diff --git a/src/email-templates/new_company_application_company.handlebars b/src/email-templates/new_company_application_company.handlebars index 9a6085e0..9d2c616a 100644 --- a/src/email-templates/new_company_application_company.handlebars +++ b/src/email-templates/new_company_application_company.handlebars @@ -1,5 +1,5 @@

Your application has been validated!

-

We will now review your application to determine the trustworthiness of your company. +

We will now review your application. In the meantime, you can complete your registration by logging into your account and begin creating offers. Please note that your offers will remain hidden from the public until your company is approved.

Your Application ID is {{applicationId}} and you registered {{companyName}}.

diff --git a/src/models/CompanyApplication.js b/src/models/CompanyApplication.js index b988b4d6..36ac5f4c 100644 --- a/src/models/CompanyApplication.js +++ b/src/models/CompanyApplication.js @@ -173,7 +173,7 @@ export const isRejectable = (application) => { }; -CompanyApplicationSchema.methods.companyValidation = function() { +CompanyApplicationSchema.methods.verifyCompany = function() { if (this.isVerified) throw new Error(CompanyApplicationRules.APPLICATION_ALREADY_VALIDATED.msg); diff --git a/src/services/account.js b/src/services/account.js index 12831d3e..b66ef251 100644 --- a/src/services/account.js +++ b/src/services/account.js @@ -31,7 +31,7 @@ class AccountService { await Account.create({ email, - password: (password), + password, company, }); } diff --git a/test/end-to-end/apply/company/index.js b/test/end-to-end/apply/company/index.js index 9afb627c..28c36163 100644 --- a/test/end-to-end/apply/company/index.js +++ b/test/end-to-end/apply/company/index.js @@ -121,13 +121,19 @@ describe("POST /apply/company", () => { })); }); - test("Should replace application if new one is created after 10 minutes", async () => { + test("Should update old application if new one is created after 10 minutes", async () => { const application = { email: "test3@test.com", password: "password123", companyName: "Testing company", motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", }; + const updated_application = { + email: "test3@test.com", + password: "password123", + companyName: "Updated Testing company", + motivation: "This company has a very valid motivation, because otherwise the tests would not exist.", + }; const res1 = await request() .post("/apply/company") @@ -140,11 +146,12 @@ describe("POST /apply/company", () => { const res2 = await request() .post("/apply/company") - .send(application) + .send(updated_application) .expect(StatusCodes.OK); - expect(await CompanyApplication.findOne({ _id: res1.body._id })).toBeFalsy(); - expect(await CompanyApplication.findOne({ _id: res2.body._id })).toBeTruthy(); + expect(await CompanyApplication.findOne({ _id: res1.body._id })).toBeTruthy(); + expect(res1.body.id).toBe(res2.body.id); + expect(res2.body.companyName).toBe(updated_application.companyName); Date.now = TempRealDate; }); diff --git a/test/end-to-end/auth.js b/test/end-to-end/auth.js index 50ad6884..601f82ce 100644 --- a/test/end-to-end/auth.js +++ b/test/end-to-end/auth.js @@ -325,7 +325,7 @@ describe("Password recovery endpoint test", () => { res = await request() .get(`/auth/recover/${generatedToken}/confirm`); - expect(res.status).toBe(HTTPStatus.GONE); + expect(res.status).toBe(HTTPStatus.FORBIDDEN); expect(res.body).toHaveProperty("errors"); expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.EXPIRED_TOKEN); @@ -380,7 +380,7 @@ describe("Password recovery endpoint test", () => { .post(`/auth/recover/${generatedToken}/confirm`) .send({ password: newPassword }); - expect(res.status).toBe(HTTPStatus.GONE); + expect(res.status).toBe(HTTPStatus.FORBIDDEN); expect(res.body).toHaveProperty("errors"); expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.EXPIRED_TOKEN); diff --git a/test/end-to-end/auth/recover/:token/confirm.js b/test/end-to-end/auth/recover/:token/confirm.js index 5ebe2950..2125fd5d 100644 --- a/test/end-to-end/auth/recover/:token/confirm.js +++ b/test/end-to-end/auth/recover/:token/confirm.js @@ -74,7 +74,7 @@ describe("GET /auth/recover/:token/confirm", () => { res = await request() .get(`/auth/recover/${generatedToken}/confirm`); - expect(res.status).toBe(StatusCodes.GONE); + expect(res.status).toBe(StatusCodes.FORBIDDEN); expect(res.body).toHaveProperty("errors"); expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.EXPIRED_TOKEN); @@ -164,7 +164,7 @@ describe("POST /auth/recover/:token/confirm", () => { .post(`/auth/recover/${generatedToken}/confirm`) .send({ password: newPassword }); - expect(res.status).toBe(StatusCodes.GONE); + expect(res.status).toBe(StatusCodes.FORBIDDEN); expect(res.body).toHaveProperty("errors"); expect(res.body.errors[0]).toHaveProperty("msg", ValidationReasons.EXPIRED_TOKEN);