diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index e30d012..f5e8692 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -2,7 +2,6 @@ name: Node.js API CI on: workflow_dispatch: - jobs: approved: diff --git a/.husky/pre-push b/.husky/pre-push index 7f9e744..669b661 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -2,6 +2,4 @@ . "$(dirname "$0")/_/husky.sh" cd backend-app -# disbale jest for now as it is not working -# npx jest - +npm test diff --git a/backend-app/.env.example b/backend-app/.env.example index 62d8bfb..deeaf3d 100644 --- a/backend-app/.env.example +++ b/backend-app/.env.example @@ -1,16 +1,16 @@ NODE_ENV = "development" -API_VERSION = "v1" +API_VERSION = "1.0.0" MONGO_URI = "mongodb://localhost:27017/S-W-O" MONGO_URI_TEST = "mongodb://localhost:27017/S-W-O-TEST" PORT = 5000 ADMIN_EMAIL = "admin@swf.com" ADMIN_PASSWORD = "password123418746" -ACCESS_TOKEN_SECRET = "0d9acc2b4953578b7ed29c443b313082e3bd14c07f9747a6b65797a254137a9d175d95ce3faaf5f60f6d5f57dfa4bcd58151a3cc262aecb428592cee6f7c964b040ac46b4efb64171e8f3660ccf948189737d8d747f3f7f7c267277b4f7ff6000f2df0aa9b58b28e86f58f4a9e07748a31c771fc74306722d4416e024d17ce26" +ACCESS_TOKEN_SECRET = "YourAccessTokenSecretKey" ACCESS_TOKEN_EXPIRY_TIME = "1d" -REFRESH_TOKEN_SECRET = "360c3a51d4cb6b57a6f899996a59ebaa0a97aa15cb00462f4c5d4e76195ac01c80f78c2887c39fc8c8fd4035ba8214634c713cddcf07de957d37d094f30ada70855caee0d5484ecddad57ed1e4361ebb55c9d568f357aaece7cdbe207f50191fb711eda1cb17997371fb80706a282c17ebf7b8bab2e84642869640797bb7bd2d" +REFRESH_TOKEN_SECRET = "YourRefreshTokenSecretKey" REFRESH_TOKEN_EXPIRY_TIME = "7d" REQUIRE_ACTIVATION = false RATE_LIMIT_PER_HOUR = 500 -GITHUB_OAUTH_CLIENT_ID = "Iv1.6f4b4b8b0b1b4b8b" -GITHUB_OAUTH_CLIENT_SECRET = "6f4b4b8b0b1b4b8b6f4b4b8b0b1b4b8b" -GITHUB_OAUTH_REDIRECT_URL = "http://localhost:3000/auth/github/callback" +OAUTH_CLIENT_ID_GITHUB = "Iv1.6f4b4b8b0b1b4b8b" +OAUTH_CLIENT_SECRET_GITHUB = "6f4b4b8b0b1b4b8b6f4b4b8b0b1b4b8b" +OAUTH_REDIRECT_URL_GITHUB = "http://localhost:3000/auth/github/callback" diff --git a/backend-app/.eslintrc.js b/backend-app/.eslintrc.js index 8e0708d..3142415 100644 --- a/backend-app/.eslintrc.js +++ b/backend-app/.eslintrc.js @@ -5,7 +5,6 @@ module.exports = { 'accessor-pairs': 'error', 'array-callback-return': 'error', 'block-scoped-var': 'error', - 'class-methods-use-this': 'error', complexity: ['error', 10], 'consistent-return': 'off', 'default-case': 'error', @@ -52,7 +51,7 @@ module.exports = { 'no-sequences': 'error', 'no-throw-literal': 'error', 'no-unmodified-loop-condition': 'error', - 'no-unused-expressions': 'error', + 'no-unused-expressions': 'warn', 'no-unused-labels': 'error', 'no-useless-call': 'error', 'no-useless-concat': 'error', diff --git a/backend-app/.eslintrc.json b/backend-app/.eslintrc.json deleted file mode 100644 index 1962053..0000000 --- a/backend-app/.eslintrc.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "env": { - "browser": true, - "node": true, - "es6": true - }, - "extends": ["eslint:recommended"], - "parserOptions": { - "ecmaVersion": 2020 - }, - "rules": { - "accessor-pairs": "error", - "array-callback-return": "error", - "block-scoped-var": "error", - "class-methods-use-this": "error", - "complexity": ["error", 10], - "consistent-return": "error", - "default-case": "error", - "dot-location": ["error", "property"], - "dot-notation": "error", - "eqeqeq": "error", - "guard-for-in": "error", - "max-classes-per-file": ["error", 1], - "no-alert": "error", - "no-caller": "error", - "no-case-declarations": "error", - "no-div-regex": "error", - "no-else-return": "error", - "no-empty-function": "error", - "no-empty-pattern": "error", - "no-eq-null": "error", - "no-eval": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-label": "error", - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-global-assign": "error", - "no-native-reassign": "error", - "no-implied-eval": "error", - "no-invalid-this": "error", - "no-iterator": "error", - "no-labels": "error", - "no-lone-blocks": "error", - "no-loop-func": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-wrappers": "error", - "no-octal-escape": "error", - "no-proto": "error", - "no-redeclare": "error", - "no-return-assign": "error", - "no-return-await": "error", - "no-script-url": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-throw-literal": "error", - "no-unmodified-loop-condition": "error", - "no-unused-expressions": "error", - "no-unused-labels": "error", - "no-useless-call": "error", - "no-useless-concat": "error", - "no-useless-escape": "error", - "no-useless-return": "error", - "no-void": "error", - "no-warning-comments": "warn", - "no-with": "error", - "prefer-promise-reject-errors": "error", - "radix": "error", - "require-await": "error", - "vars-on-top": "error", - "wrap-iife": ["error", "inside"], - "yoda": "error", - "no-console": "warn", - "no-var": "error", - "no-unused-vars": "warn", - "arrow-body-style": ["error", "as-needed"] - } -} diff --git a/backend-app/.gitignore b/backend-app/.gitignore index 78be1b5..40b0322 100644 --- a/backend-app/.gitignore +++ b/backend-app/.gitignore @@ -25,14 +25,12 @@ coverage .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release +build # Dependency directories node_modules/ jspm_packages/ -# TypeScript v1 declaration files -typings/ # Optional npm cache directory .npm diff --git a/backend-app/.husky/pre-commit b/backend-app/.husky/pre-commit deleted file mode 100755 index 9d1980c..0000000 --- a/backend-app/.husky/pre-commit +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env sh -. "$(dirname "$0")/_/husky.sh" - -cd backend-app -npx lint-staged diff --git a/backend-app/.husky/pre-push b/backend-app/.husky/pre-push deleted file mode 100755 index 5d6e8f4..0000000 --- a/backend-app/.husky/pre-push +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env sh -. "$(dirname "$0")/_/husky.sh" - -cd backend-app -jest diff --git a/backend-app/.mocharc.json b/backend-app/.mocharc.json new file mode 100644 index 0000000..4fd5c91 --- /dev/null +++ b/backend-app/.mocharc.json @@ -0,0 +1,6 @@ +{ + "extension": ["ts"], + "spec": ["tests/**/*.spec.ts", "tests/**/*.spec.js"], + "require": "tsconfig-paths/register", + "file": ["tests/env.test.ts"] +} diff --git a/backend-app/README.md b/backend-app/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/backend-app/app.js b/backend-app/app.ts similarity index 51% rename from backend-app/app.js rename to backend-app/app.ts index c720b17..067d923 100644 --- a/backend-app/app.js +++ b/backend-app/app.ts @@ -1,20 +1,21 @@ -const globalErrHandler = require('./middlewares/global_error_handler'); -const AppError = require('./utils/app_error'); -const express = require('express'); -const limiter = require('./middlewares/rate_limit'); -const bearerToken = require('express-bearer-token'); -const compression = require('compression'); -const helmet = require('helmet'); -const mongoSanitize = require('express-mongo-sanitize'); -const xss = require('xss-clean'); -const hpp = require('hpp'); -const cors = require('cors'); -const morgan = require('./middlewares/morgan'); -const swaggerDocs = require('./utils/swagger'); -const handleAPIVersion = require('./middlewares/api_version_controll'); -const { COOKIE_SECRET, CURRENT_ENV } = require('./config/app_config'); -const cookieParser = require('cookie-parser'); -const routesVersioning = require('express-routes-versioning')(); +import globalErrHandler from './middlewares/global_error_handler'; +import AppError from './utils/app_error'; +import express, { Request, Response, NextFunction } from 'express'; +import limiter from './middlewares/rate_limit'; +import bearerToken from 'express-bearer-token'; +import compression from 'compression'; +import helmet from 'helmet'; +import mongoSanitize from 'express-mongo-sanitize'; +import xss from 'xss-clean'; +import hpp from 'hpp'; +import cors from 'cors'; +import Morgan from './middlewares/morgan'; +import swaggerDocs from './utils/swagger/index'; +import handleAPIVersion from './middlewares/api_version_controll'; +import { COOKIE_SECRET, CURRENT_ENV } from './config/app_config'; +import cookieParser from 'cookie-parser'; +import routesVersioning from 'express-routes-versioning'; +import indexRouter from './routes/index'; const app = express(); @@ -24,7 +25,7 @@ app.use(express.json()); app.use(cookieParser(COOKIE_SECRET)); // use morgan for logging -app.use(morgan); +app.use(Morgan); // Allow Cross-Origin requests app.use(cors()); @@ -68,9 +69,8 @@ app.use(handleAPIVersion); // handle bearer token app.use(bearerToken()); -app.get('/', (req, res) => { +app.get('/', (_req: Request, res: Response) => { res.status(200).json({ - status: 'success', message: 'Welcome to the backend app', env: CURRENT_ENV, }); @@ -79,8 +79,8 @@ app.get('/', (req, res) => { // routes app.use( `/api`, - routesVersioning({ - '1.0.0': require('./routes/index'), + routesVersioning()({ + '1.0.0': indexRouter, }) ); @@ -88,11 +88,11 @@ app.use( swaggerDocs(app); // handle undefined Routes -app.use('*', (req, res, next) => { - const err = new AppError(404, 'fail', 'Route Not Found', req.originalUrl); - next(err, req, res, next); +app.use('*', (req: Request, _res: Response, next: NextFunction) => { + const err = new AppError(404, 'Route Not Found', req.originalUrl); + next(err); }); app.use(globalErrHandler); -module.exports = app; +export default app; diff --git a/backend-app/config/app_config.ts b/backend-app/config/app_config.ts index b890542..321da84 100644 --- a/backend-app/config/app_config.ts +++ b/backend-app/config/app_config.ts @@ -3,8 +3,17 @@ import dotenv from 'dotenv'; import fs from 'fs'; // load env file -const envFile = fs.existsSync('.env') ? '.env' : '.env.example'; -dotenv.config({ path: join(__dirname, `../${envFile}`) }); +const envMode = process.env.NODE_ENV?.toLowerCase(); +const envFile = + envMode === 'production' + ? '.env.production' + : fs.existsSync('.env') + ? '.env' + : '.env.example'; + +if (envFile) { + dotenv.config({ path: join(__dirname, `../${envFile}`) }); +} // parse boolean values const parseBoolean = (value: string): boolean => value === 'true'; @@ -17,12 +26,15 @@ export const MONGO_URI_TEST = process.env.MONGO_URI_TEST; export const PORT = process.env.PORT; export const ADMIN_EMAIL = process.env.ADMIN_EMAIL; export const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD; -export const REQUIRE_ACTIVATION = parseBoolean(process.env.REQUIRE_ACTIVATION); -export const RATE_LIMIT_PER_HOUR = process.env.RATE_LIMIT_PER_HOUR; -export const GITHUB_OAUTH_CLIENT_ID = process.env.GITHUB_OAUTH_CLIENT_ID; -export const GITHUB_OAUTH_CLIENT_SECRET = - process.env.GITHUB_OAUTH_CLIENT_SECRET; -export const GITHUB_OAUTH_REDIRECT_URL = process.env.GITHUB_OAUTH_REDIRECT_URL; +export const REQUIRE_ACTIVATION = parseBoolean( + process.env.REQUIRE_ACTIVATION as string +); +export const RATE_LIMIT_PER_HOUR = process.env + .RATE_LIMIT_PER_HOUR as unknown as number; +export const OAUTH_CLIENT_ID_GITHUB = process.env.OAUTH_CLIENT_ID_GITHUB; +export const OAUTH_CLIENT_SECRET_GITHUB = + process.env.OAUTH_CLIENT_SECRET_GITHUB; +export const OAUTH_REDIRECT_URL_GITHUB = process.env.OAUTH_REDIRECT_URL_GITHUB; export const ACCESS_TOKEN_SECRET = process.env.ACCESS_TOKEN_SECRET; export const ACCESS_TOKEN_EXPIRY_TIME = process.env.ACCESS_TOKEN_EXPIRY_TIME; export const REFRESH_TOKEN_SECRET = process.env.REFRESH_TOKEN_SECRET; diff --git a/backend-app/config/logger_config.ts b/backend-app/config/logger_config.ts index c090053..4d03ddc 100644 --- a/backend-app/config/logger_config.ts +++ b/backend-app/config/logger_config.ts @@ -43,6 +43,10 @@ const consoleOptions = { format.timestamp({ format: 'HH:mm:ss MM-DD-YYYY', }), + format((info) => { + info.level = info.level.toUpperCase(); + return info; + })(), format.colorize({ all: true }), format.timestamp(), formatLogMessage diff --git a/backend-app/constants/actions.js b/backend-app/constants/actions.ts similarity index 75% rename from backend-app/constants/actions.js rename to backend-app/constants/actions.ts index 099975a..40ab091 100644 --- a/backend-app/constants/actions.js +++ b/backend-app/constants/actions.ts @@ -1,6 +1,3 @@ -/** - * @enum {string} - */ const Actions = { DELETE_USER: 'DELETE_USER', BAN_USER: 'BAN_USER', @@ -9,6 +6,5 @@ const Actions = { REMOVE_SUPER_ADMIN: 'REMOVE_SUPER_ADMIN', MANAGE_ROLES: 'MANAGE_ROLES', }; -Object.freeze(Actions); -module.exports = Actions; +export default Actions; diff --git a/backend-app/constants/default_roles.js b/backend-app/constants/default_roles.js deleted file mode 100644 index 8aa36e4..0000000 --- a/backend-app/constants/default_roles.js +++ /dev/null @@ -1,25 +0,0 @@ -const Actions = require('./actions'); -const Roles = { - SUPER_ADMIN: { - type: 'SUPER_ADMIN', - authorities: Object.values(Actions), - restrictions: [], - }, - ADMIN: { - type: 'ADMIN', - authorities: [ - Actions.DELETE_USER, - Actions.UPDATE_USER, - Actions.BAN_USER, - ], - restrictions: [], - }, - USER: { - type: 'USER', - authorities: [Actions.UPDATE_CALANDER], - restrictions: [], - }, -}; -Object.freeze(Roles); - -module.exports = Roles; diff --git a/backend-app/constants/meta_data.js b/backend-app/constants/meta_data.ts similarity index 81% rename from backend-app/constants/meta_data.js rename to backend-app/constants/meta_data.ts index 4ef58c2..bcfded0 100644 --- a/backend-app/constants/meta_data.js +++ b/backend-app/constants/meta_data.ts @@ -1,10 +1,10 @@ /** - * @param {import('mongoose').Schema} model + * @param {Schema} model * @returns {void} * @description Add common fields to a model * **/ -exports.apply = (model) => { +const apply = (model: any): void => { model.add({ deleted: { type: Boolean, @@ -25,3 +25,7 @@ exports.apply = (model) => { }, }); }; + +export default { + apply, +}; diff --git a/backend-app/controllers/auth_controllers/auth_controller.js b/backend-app/controllers/auth_controllers/auth_controller.js deleted file mode 100644 index e163b67..0000000 --- a/backend-app/controllers/auth_controllers/auth_controller.js +++ /dev/null @@ -1,379 +0,0 @@ -const { promisify } = require('util'); -const mongoose = require('mongoose'); -const validator = require('validator'); -const User = require('../../models/user/user_model'); -const AppError = require('../../utils/app_error'); -const Role = require('../../utils/authorization/role/role'); -const { REQUIRE_ACTIVATION } = require('../../config/app_config'); -const { - getGithubOAuthUser, - getGithubOAuthToken, - getGithubOAuthUserPrimaryEmail, -} = require('../../utils/authorization/github'); -const role = new Role(); -const AuthUtils = require('../../utils/authorization/auth_utils'); -const searchCookies = require('../../utils/searchCookie'); - -const generateActivationKey = async () => { - const randomBytesPromiseified = promisify(require('crypto').randomBytes); - const activationKey = (await randomBytesPromiseified(32)).toString('hex'); - return activationKey; -}; - -exports.githubHandler = async (req, res, next) => { - try { - const Roles = await role.getRoles(); - const { code, redirect_url } = req.query; - if (!redirect_url) - throw new AppError(400, 'fail', 'Please provide redirect_url'); - if (!code) throw new AppError(400, 'fail', 'Please provide code'); - const { access_token } = await getGithubOAuthToken(code); - if (!access_token) throw new AppError(400, 'fail', 'Invalid code'); - const githubUser = await getGithubOAuthUser(access_token); - const primaryEmail = await getGithubOAuthUserPrimaryEmail(access_token); - const exists = await User.findOne({ email: primaryEmail }); - if (exists) { - const accessToken = AuthUtils.generateAccessToken(exists._id); - const refreshToken = AuthUtils.generateRefreshToken(exists._id); - AuthUtils.setAccessTokenCookie( - res, - accessToken - ).setRefreshTokenCookie(res, refreshToken); - } - if (!githubUser) - throw new AppError(400, 'fail', 'Invalid access token'); - const createdUser = await User.create({ - name: githubUser.name, - email: primaryEmail, - password: null, - address: githubUser.location, - roles: [Roles.USER.type], - authorities: Roles.USER.authorities, - restrictions: Roles.USER.restrictions, - githubOauthAccessToken: access_token, - active: true, - }); - - const accessToken = AuthUtils.generateAccessToken(createdUser._id); - const refreshToken = AuthUtils.generateRefreshToken(createdUser._id); - AuthUtils.setAccessTokenCookie(res, accessToken).setRefreshTokenCookie( - res, - refreshToken - ); - //redirect user to redirect url - res.redirect(redirect_url); - } catch (err) { - next(err); - } -}; -exports.login = async (req, res, next) => { - try { - const { email, password } = req.body; - - // 1) check if email and password existos - if (!email || !password) { - return next( - new AppError(404, 'fail', 'Please provide email or password') - ); - } - - if (!validator.isEmail(email)) { - return next(new AppError(400, 'fail', 'Invalid email format')); - } - - // 2) check if user exist and password is correct - const user = await User.findOne({ - email, - }).select('+password'); - // Check if the account is banned - if (user && user?.accessRestricted) - throw new AppError( - 403, - 'fail', - 'Your account has been banned. Please contact the admin for more information.' - ); - - if (!user || !(await user.correctPassword(password, user.password))) { - return next( - new AppError(401, 'fail', 'Email or Password is wrong') - ); - } - - // 3) All correct, send accessToken & refreshToken to client via cookie - const accessToken = AuthUtils.generateAccessToken(user._id); - const refreshToken = AuthUtils.generateRefreshToken(user._id); - AuthUtils.setAccessTokenCookie(res, accessToken).setRefreshTokenCookie( - res, - refreshToken - ); - - // Remove the password from the output - user.password = undefined; - - res.status(200).json({ - accessToken, - user, - }); - } catch (err) { - next(err); - } -}; - -exports.signup = async (req, res, next) => { - try { - const activationKey = await generateActivationKey(); - const Roles = await role.getRoles(); - const userpayload = { - name: req.body.name, - email: req.body.email, - password: req.body.password, - roles: [Roles.USER.type], - authorities: Roles.USER.authorities, - active: !REQUIRE_ACTIVATION, - restrictions: Roles.USER.restrictions, - ...(REQUIRE_ACTIVATION && { activationKey }), - }; - const user = await User.create(userpayload); - const accessToken = AuthUtils.generateAccessToken(user._id); - const refreshToken = AuthUtils.generateRefreshToken(user._id); - AuthUtils.setAccessTokenCookie(res, accessToken).setRefreshTokenCookie( - res, - refreshToken - ); - // Remove the password and activation key from the output - user.password = undefined; - user.activationKey = undefined; - - res.status(201).json({ - accessToken, - user, - }); - } catch (err) { - next(err); - } -}; - -exports.tokenRefresh = async (req, res, next) => { - try { - const refreshToken = searchCookies(req, 'refresh_token'); - if (!refreshToken) - throw new AppError(400, 'fail', 'You have to login to continue.'); - const refreshTokenPayload = - await AuthUtils.verifyRefreshToken(refreshToken); - if (!refreshTokenPayload || !refreshTokenPayload.id) - throw new AppError(400, 'fail', 'Invalid refresh token'); - const user = await User.findById(refreshTokenPayload.id); - if (!user) throw new AppError(400, 'fail', 'Invalid refresh token'); - const accessToken = AuthUtils.generateAccessToken(user._id); - //set or override accessToken cookie. - AuthUtils.setAccessTokenCookie(res, accessToken); - res.sendStatus(204); - } catch (err) { - next(err); - } -}; -exports.logout = async (req, res, next) => { - try { - const accessToken = searchCookies(req, 'access_token'); - if (!accessToken) - throw new AppError(400, 'fail', 'Please provide access token'); - const accessTokenPayload = - await AuthUtils.verifyAccessToken(accessToken); - if (!accessTokenPayload || !accessTokenPayload.id) - throw new AppError(400, 'fail', 'Invalid access token'); - res.sendStatus(204); - } catch (err) { - next(err); - } -}; - -exports.activateAccount = async (req, res, next) => { - try { - const { id, activationKey } = req.query; - - if (!activationKey) { - return next( - new AppError(400, 'fail', 'Please provide activation key') - ); - } - if (!id) { - return next(new AppError(400, 'fail', 'Please provide user id')); - } - - // check if a valid id - if (!mongoose.Types.ObjectId.isValid(id)) { - return next( - new AppError(400, 'fail', 'Please provide a valid user id') - ); - } - - const user = await User.findOne({ - _id: id, - }).select('+activationKey'); - - if (!user) { - return next(new AppError(404, 'fail', 'User does not exist')); - } - if (user.active) { - return next(new AppError(409, 'fail', 'User is already active')); - } - - // verify activation key - if (activationKey !== user.activationKey) { - return next(new AppError(400, 'fail', 'Invalid activation key')); - } - // activate user - user.active = true; - user.activationKey = undefined; - await user.save(); - // Remove the password from the output - user.password = undefined; - - res.status(200).json({ - user, - }); - } catch (err) { - next(err); - } -}; - -exports.updatePassword = async (req, res, next) => { - try { - const { email, resetKey, password } = req.body; - - if (!validator.isEmail(email)) { - return next(new AppError(400, 'fail', 'Invalid email format')); - } - - const user = await User.findOne({ email }).select('+password'); - - if (!resetKey) { - return next(new AppError(400, 'fail', 'Please provide reset key')); - } - - if (resetKey !== user.resetKey) { - return next(new AppError(400, 'fail', 'Invalid reset key')); - } - - user.password = password; - user.resetKey = undefined; - await user.save(); - - const token = createToken(user.id); - user.password = undefined; - - res.status(200).json({ - status: 'success', - token, - user, - }); - } catch (err) { - next(err); - } -}; - -exports.forgotPassword = async (req, res, next) => { - try { - const { email } = req.body; - - if (!email) { - return next(new AppError(400, 'fail', 'Please provide email')); - } - - if (!validator.isEmail(email)) { - return next(new AppError(400, 'fail', 'Invalid email format')); - } - - const user = await User.findOne({ email }); - - if (!user) { - return next( - new AppError(404, 'fail', 'User with this email does not exist') - ); - } - - const resetKey = user.generateResetKey(); - await user.save(); - - Logger.info( - `User ${user.name} with email ${user.email} has requested for password reset with reset key ${resetKey}` - ); - - // send email with reset key - // eslint-disable-next-line no-warning-comments - // TODO: send email with reset key - - res.status(200).json({ - status: 'success', - }); - } catch (err) { - next(err); - } -}; - -exports.protect = async (req, res, next) => { - try { - const accessToken = searchCookies(req, 'access_token') || req.token; - if (!accessToken) - return next(new AppError(401, 'fail', 'Please login to continue')); - - const accessTokenPayload = - await AuthUtils.verifyAccessToken(accessToken); - if (!accessTokenPayload || !accessTokenPayload.id) - throw new AppError(401, 'fail', 'Invalid access token'); - // 3) check if the user is exist (not deleted) - const user = await User.findById(accessTokenPayload.id).select( - 'accessRestricted active' - ); - if (!user) { - return next( - new AppError(401, 'fail', 'This user is no longer exist') - ); - } - - // Check if the account is banned - if (user?.accessRestricted) - return next( - new AppError( - 403, - 'fail', - 'Your account has been banned. Please contact the admin for more information.' - ) - ); - req.user = user; - // check if account is active - if (!user.active) - return next( - new AppError( - 403, - 'fail', - 'Your account is not active. Please activate your account to continue.' - ) - ); - - next(); - } catch (err) { - // check if the token is expired - if (err.name === 'TokenExpiredError') { - return next(new AppError(401, 'fail', 'Your token is expired')); - } - next(err); - } -}; - -// Authorization check if the user have rights to do this action -exports.restrictTo = - (...roles) => - (req, res, next) => { - const roleExist = roles.some((role) => req.user.roles.includes(role)); - if (!roleExist) { - return next( - new AppError( - 403, - 'fail', - 'You are not allowed to do this action' - ) - ); - } - next(); - }; diff --git a/backend-app/controllers/auth_controllers/auth_controller.ts b/backend-app/controllers/auth_controllers/auth_controller.ts new file mode 100644 index 0000000..7287c98 --- /dev/null +++ b/backend-app/controllers/auth_controllers/auth_controller.ts @@ -0,0 +1,369 @@ +import mongoose from 'mongoose'; +import { IReq, IRes, INext } from '@interfaces/vendors'; +import { promisify } from 'util'; +import AppError from '@utils/app_error'; +import Role from '@utils/authorization/roles/role'; +import { REQUIRE_ACTIVATION } from '@config/app_config'; +import { + getGithubOAuthUser, + getGithubOAuthToken, + getGithubOAuthUserPrimaryEmail, +} from '@utils/authorization/github'; +import AuthUtils from '@utils/authorization/auth_utils'; +import searchCookies from '@utils/searchCookie'; +import User from '@models/user/user_model'; +import { Request, Response, NextFunction } from 'express'; +import { IUser } from '@root/interfaces/models/i_user'; + +const generateActivationKey = async () => { + const randomBytesPromiseified = promisify(require('crypto').randomBytes); + const activationKey = (await randomBytesPromiseified(32)).toString('hex'); + return activationKey; +}; + +export const githubHandler = async ( + req: Request, + res: Response, + next: NextFunction +) => { + try { + const Roles = await Role.getRoles(); + // check if user role exists + if (!Roles.USER) + throw new AppError( + 500, + 'User role does not exist. Please contact the admin.' + ); + const { code, redirect_url } = req.query as { + code: string; + redirect_url: string; + }; + if (!redirect_url) + throw new AppError(400, 'Please provide redirect_url'); + if (typeof redirect_url !== 'string') + throw new AppError(400, 'Invalid redirect_url'); + if (!code) throw new AppError(400, 'Please provide code'); + const { access_token } = await getGithubOAuthToken(code); + if (!access_token) throw new AppError(400, 'Invalid code'); + const githubUser = await getGithubOAuthUser(access_token as string); + const primaryEmail = await getGithubOAuthUserPrimaryEmail( + access_token as string + ); + const exists = await User.findOne({ email: primaryEmail }); + if (exists) { + const accessToken = AuthUtils.generateAccessToken( + exists._id.toString() + ); + const refreshToken = AuthUtils.generateRefreshToken( + exists._id.toString() + ); + AuthUtils.setAccessTokenCookie(res, accessToken); + AuthUtils.setRefreshTokenCookie(res, refreshToken); + } + if (!githubUser) throw new AppError(400, 'Invalid access token'); + const createdUser = await User.create({ + name: githubUser.name, + email: primaryEmail, + password: null, + address: githubUser.location, + roles: [Roles.USER.name], + authorities: Roles.USER.authorities, + restrictions: Roles.USER.restrictions, + githubOauthAccessToken: access_token, + active: true, + }); + + const accessToken = AuthUtils.generateAccessToken( + createdUser._id.toString() + ); + const refreshToken = AuthUtils.generateRefreshToken( + createdUser._id.toString() + ); + AuthUtils.setAccessTokenCookie(res, accessToken); + AuthUtils.setRefreshTokenCookie(res, refreshToken); + //redirect user to redirect url + res.redirect(redirect_url); + } catch (err) { + next(err); + } +}; + +export const login = async ( + req: Request, + res: Response, + next: NextFunction +) => { + try { + const { email, password } = req.body as { + email: string; + password: string; + }; + + // 1) check if password exist + if (!password) { + throw new AppError(400, 'Please provide a password'); + } + // to type safty on password + if (typeof password !== 'string') { + throw new AppError(400, 'Invalid password format'); + } + + // 2) check if user exist and password is correct + const user = await User.findOne({ + email, + }).select('+password'); + + // check if password exist and it is a string + if (!user?.password || typeof user.password !== 'string') + throw new AppError(400, 'Invalid email or password'); + + // Check if the account is banned + if (user && user?.accessRestricted) + throw new AppError( + 403, + 'Your account has been banned. Please contact the admin for more information.' + ); + + if (!user || !(await user.correctPassword(password, user.password))) { + throw new AppError(401, 'Email or Password is wrong'); + } + + // 3) All correct, send accessToken & refreshToken to client via cookie + const accessToken = AuthUtils.generateAccessToken(user._id.toString()); + const refreshToken = AuthUtils.generateRefreshToken( + user._id.toString() + ); + AuthUtils.setAccessTokenCookie(res, accessToken); + AuthUtils.setRefreshTokenCookie(res, refreshToken); + + // Remove the password from the output + user.password = undefined; + + res.status(200).json({ + accessToken, + user, + }); + } catch (err) { + next(err); + } +}; + +export const signup = async ( + req: Request, + res: Response, + next: NextFunction +) => { + try { + const activationKey = await generateActivationKey(); + const Roles = await Role.getRoles(); + + // check if user role exists + if (!Roles.USER) + throw new AppError( + 500, + 'User role does not exist. Please contact the admin.' + ); + + // check if password is provided + if (!req.body.password) + throw new AppError(400, 'Please provide a password'); + + const userpayload = { + name: req.body.name, + email: req.body.email, + password: req.body.password, + roles: [Roles.USER.name], + authorities: Roles.USER.authorities, + active: !REQUIRE_ACTIVATION, + restrictions: Roles.USER.restrictions, + ...(REQUIRE_ACTIVATION && { activationKey }), + }; + const user = await User.create(userpayload); + const accessToken = AuthUtils.generateAccessToken(user._id.toString()); + const refreshToken = AuthUtils.generateRefreshToken( + user._id.toString() + ); + AuthUtils.setAccessTokenCookie(res, accessToken); + AuthUtils.setRefreshTokenCookie(res, refreshToken); + // Remove the password and activation key from the output + user.password = undefined; + user.activationKey = undefined; + + res.status(201).json({ + accessToken, + user, + }); + } catch (err) { + next(err); + } +}; + +export const tokenRefresh = async ( + req: Request, + res: Response, + next: NextFunction +) => { + try { + // get the refresh token from httpOnly cookie + const refreshToken = searchCookies(req, 'refresh_token'); + if (!refreshToken) + throw new AppError(400, 'You have to login to continue.'); + const refreshTokenPayload = + await AuthUtils.verifyRefreshToken(refreshToken); + if (!refreshTokenPayload || !refreshTokenPayload._id) + throw new AppError(400, 'Invalid refresh token'); + const user = await User.findById(refreshTokenPayload._id); + if (!user) throw new AppError(400, 'Invalid refresh token'); + const accessToken = AuthUtils.generateAccessToken(user._id.toString()); + //set or override accessToken cookie. + AuthUtils.setAccessTokenCookie(res, accessToken); + res.sendStatus(204); + } catch (err) { + next(err); + } +}; +export const logout = async ( + req: Request, + res: Response, + next: NextFunction +) => { + try { + const accessToken = searchCookies(req, 'access_token'); + if (!accessToken) + throw new AppError(400, 'Please provide access token'); + const accessTokenPayload = + await AuthUtils.verifyAccessToken(accessToken); + if (!accessTokenPayload || !accessTokenPayload._id) + throw new AppError(400, 'Invalid access token'); + res.sendStatus(204); + } catch (err) { + next(err); + } +}; + +interface ActivationParams { + id: string; + activationKey: string; +} + +export const activateAccount = async ( + req: Request, + res: Response, + next: NextFunction +) => { + try { + const { id, activationKey } = req.query as unknown as ActivationParams; + + if (!activationKey) { + throw new AppError(400, 'Please provide activation key'); + } + if (!id) { + throw new AppError(400, 'Please provide user id'); + } + + // check if a valid id + if (!mongoose.Types.ObjectId.isValid(id)) { + throw new AppError(400, 'Please provide a valid user id'); + } + + const user = await User.findOne({ + _id: id, + }).select('+activationKey'); + + if (!user) { + throw new AppError(404, 'User does not exist'); + } + if (user.active) { + throw new AppError(409, 'User is already active'); + } + + // verify activation key + if (activationKey !== user.activationKey) { + throw new AppError(400, 'Invalid activation key'); + } + // activate user + user.active = true; + user.activationKey = undefined; + await user.save(); + // Remove the password from the output + user.password = undefined; + + res.status(200).json({ + user, + }); + } catch (err) { + next(err); + } +}; + +export const protect = async ( + req: Request, + res: Response, + next: NextFunction +) => { + try { + const accessToken = searchCookies(req, 'access_token'); + + if (!accessToken) throw new AppError(401, 'Please login to continue'); + + const accessTokenPayload = + await AuthUtils.verifyAccessToken(accessToken); + + if (!accessTokenPayload || !accessTokenPayload._id) + throw new AppError(401, 'Invalid access token'); + // 3) check if the user is exist (not deleted) + const user: IUser = await User.findById(accessTokenPayload._id).select( + 'accessRestricted active roles authorities restrictions name email' + ); + if (!user) { + throw new AppError(401, 'This user is no longer exist'); + } + + // Check if the account is banned + if (user?.accessRestricted) + throw new AppError( + 403, + 'Your account has been banned. Please contact the admin for more information.' + ); + + // check if account is active + if (!user.active) + throw new AppError( + 403, + 'Your account is not active. Please activate your account to continue.' + ); + + // Create a new request object with the user property set to the user object + + req.user = user; + next(); + } catch (err) { + // check if the token is expired + if (err.name === 'TokenExpiredError') { + return next(new AppError(401, 'Your token is expired')); + } + if (err.name === 'JsonWebTokenError') { + return next(new AppError(401, err.message)); + } + next(err); + } +}; + +// Authorization check if the user have rights to do this action +export const restrictTo = + (...roles: string[]) => + (req: IReq, res: IRes, next: INext) => { + try { + const roleExist = roles.some((role) => + req.user.roles.includes(role) + ); + if (!roleExist) + throw new AppError( + 403, + 'You are not allowed to do this action' + ); + next(); + } catch (err) { + next(err); + } + }; diff --git a/backend-app/controllers/auth_controllers/github_controller.js b/backend-app/controllers/auth_controllers/github_controller.ts similarity index 61% rename from backend-app/controllers/auth_controllers/github_controller.js rename to backend-app/controllers/auth_controllers/github_controller.ts index fc0a348..d594aae 100644 --- a/backend-app/controllers/auth_controllers/github_controller.js +++ b/backend-app/controllers/auth_controllers/github_controller.ts @@ -1,9 +1,14 @@ -const axios = require('axios'); -const AppError = require('../../utils/app_error'); +import axios from 'axios'; +import Repository from '@interfaces/github_repo'; +import AppError from '@utils/app_error'; +import { INext, IReq, IRes } from '@interfaces/vendors'; -exports.getRecentRepo = async (req, res, next) => { - const { githubOauthAccessToken } = req.user; +export const getRecentRepo = async (req: IReq, res: IRes, next: INext) => { try { + if (!req.user) { + throw new AppError(401, 'You are not logged in'); + } + const { githubOauthAccessToken } = req.user; const userRepositories = await axios.get( 'https://api.github.com/user/repos', { @@ -13,7 +18,7 @@ exports.getRecentRepo = async (req, res, next) => { } ); const mappedUserRepositories = userRepositories.data.map( - (repository) => ({ + (repository: any): Repository => ({ id: repository.id, name: repository.name, full_name: repository.full_name, @@ -28,10 +33,14 @@ exports.getRecentRepo = async (req, res, next) => { url: repository.url, }) ); - if (mappedUserRepositories.length <= 0) - throw new AppError(400, 'fail', 'No repositories found'); + if (mappedUserRepositories.length <= 0) { + throw new AppError(400, 'No repositories found'); + } + const sortedRepository = mappedUserRepositories.sort( - (a, b) => new Date(b.repoCreatedAt) - new Date(a.repoCreatedAt) + (a: Repository, b: Repository) => + new Date(b.repoCreatedAt).getTime() - + new Date(a.repoCreatedAt).getTime() ); const recentRepository = sortedRepository[0]; diff --git a/backend-app/controllers/auth_controllers/password_management.ts b/backend-app/controllers/auth_controllers/password_management.ts new file mode 100644 index 0000000..aacbc98 --- /dev/null +++ b/backend-app/controllers/auth_controllers/password_management.ts @@ -0,0 +1,82 @@ +import User from '@models/user/user_model'; +import logger from '@utils/logger'; +import AppError from '@utils/app_error'; +import generateTokens from '@utils/authorization/generate_tokens'; +import validator from 'validator'; +import { NextFunction, Request, Response } from 'express'; + +export const updatePassword = async ( + req: Request, + res: Response, + next: NextFunction +) => { + try { + const { email, resetKey, password } = req.body; + + if (!validator.isEmail(email)) + throw new AppError(400, 'Invalid email format'); + + const user = await User.findOne({ email }).select('+password'); + + if (!user) + throw new AppError(404, 'User with this email does not exist'); + + if (!resetKey) throw new AppError(400, 'Please provide reset key'); + + if (!user.resetKey) throw new AppError(400, 'Invalid reset key'); + + if (resetKey !== user.resetKey) + throw new AppError(400, 'Invalid reset key'); + + user.password = password; + user.resetKey = undefined; + await user.save(); + + const token = generateTokens(user.id); + user.password = undefined; + + res.status(200).json({ + token, + user, + }); + } catch (err) { + next(err); + } +}; + +export const forgotPassword = async ( + req: Request, + res: Response, + next: NextFunction +) => { + try { + const { email } = req.body; + + if (!email) throw new AppError(400, 'Please provide email'); + + if (!validator.isEmail(email)) + throw new AppError(400, 'Invalid email format'); + + const user = await User.findOne({ email }); + + if (!user) + throw new AppError(404, 'User with this email does not exist'); + + const resetKey = user.generateResetKey(); + await user.save(); + + logger.info( + `User ${user.name} with email ${user.email} has requested for password reset with reset key ${resetKey}` + ); + + // send email with reset key + // eslint-disable-next-line no-warning-comments + // TODO: send email with reset key + + res.status(200).json({ + message: 'Email with reset key sent successfully', + }); + } catch (err) { + next(err); + } +}; diff --git a/backend-app/controllers/base_controller.ts b/backend-app/controllers/base_controller.ts index d48d70b..1eeebe5 100644 --- a/backend-app/controllers/base_controller.ts +++ b/backend-app/controllers/base_controller.ts @@ -1,13 +1,8 @@ -import { Request, Response, NextFunction, RequestHandler } from 'express'; +import { NextFunction, RequestHandler } from 'express'; import { Model } from 'mongoose'; import AppError from '@utils/app_error'; import APIFeatures from '@utils/api_features'; - -interface RequestWithUser extends Request { - user?: { - _id: string; - }; -} +import { IReq, IRes } from '@interfaces/vendors'; /** * Delete a document by ID (soft delete) @@ -15,24 +10,20 @@ interface RequestWithUser extends Request { * @returns {Function} - Express middleware function */ export const deleteOne = - (Model: Model) => - async (req: RequestWithUser, res: Response, next: NextFunction) => { + (Model: Model): RequestHandler => + async (req: IReq, res: IRes, next: NextFunction): Promise => { try { const doc = await Model.findByIdAndUpdate( req.params.id, { deleted: true, - ...(req.user && { deletedBy: req.user._id }), + ...(req.user && { deletedBy: req.user?._id }), deletedAt: Date.now(), }, { new: true } ); - if (!doc) { - return next( - new AppError(404, 'fail', 'No document found with that id') - ); - } + if (!doc) throw new AppError(404, 'No document found with that id'); res.status(204).json({ data: null, @@ -49,21 +40,18 @@ export const deleteOne = */ export const updateOne = (Model: Model): RequestHandler => - async (req: RequestWithUser, res: Response, next: NextFunction) => { + async (req: IReq, res: IRes, next: NextFunction) => { try { // get the user who is updating the document - const userid = req.user._id; + const userid = req.user?._id; req.body.updatedBy = userid; - const doc = await Model.findByIdAndUpdate(req.params.id, req.body, { + const payload = new Model(req.body); + const doc = await Model.findByIdAndUpdate(req.params.id, payload, { new: true, runValidators: true, }); - if (!doc) { - return next( - new AppError(404, 'fail', 'No document found with that id') - ); - } + if (!doc) throw new AppError(404, 'No document found with that id'); res.status(200).json({ doc, @@ -79,10 +67,15 @@ export const updateOne = * @returns {Function} - Express middleware function */ export const createOne = - (Model: Model) => - async (req: RequestWithUser, res: Response, next: NextFunction) => { + (Model: Model): RequestHandler => + async (req: IReq, res: IRes, next: NextFunction) => { try { // get the user who is creating the document + if (req.user === undefined) + throw new AppError( + 401, + 'You are not authorized to perform this action' + ); const userid = req.user._id; req.body.createdBy = userid; @@ -101,16 +94,12 @@ export const createOne = * @returns {Function} - Express middleware function */ export const getOne = - (Model: Model) => - async (req: Request, res: Response, next: NextFunction) => { + (Model: Model): RequestHandler => + async (req: IReq, res: IRes, next: NextFunction) => { try { const doc = await Model.findById(req.params.id); - if (!doc) { - return next( - new AppError(404, 'fail', 'No document found with that id') - ); - } + if (!doc) throw new AppError(404, 'No document found with that id'); res.status(200).json({ doc, @@ -126,11 +115,13 @@ export const getOne = * @returns {Function} - Express middleware function */ export const getAll = - (Model: Model) => - async (req: Request, res: Response, next: NextFunction) => { + (Model: Model): RequestHandler => + async (req: IReq, res: IRes, next: NextFunction) => { try { - // const s = req.body.search; - const features = new APIFeatures(Model.find(), req.query) + const features = new APIFeatures( + Model.find(), + req.query as Record + ) .sort() .paginate(); diff --git a/backend-app/controllers/calendar_controllers/calendar_base_controller.js b/backend-app/controllers/calendar_controllers/calendar_base_controller.js deleted file mode 100644 index ebc27aa..0000000 --- a/backend-app/controllers/calendar_controllers/calendar_base_controller.js +++ /dev/null @@ -1,31 +0,0 @@ -const AppError = require('../../utils/app_error'); -const calendar_validators = require('./calendar_validators'); - -exports.updateCalendar = async (req, res, next) => { - const calendar = await calendar_validators.validateCalendar(req); - // check if user is not admin nor the owner of the calendar - if ( - calendar.createdBy !== req.user.id.toString() || - !req.user.roles.includes('ADMIN') || - !req.user.roles.includes('SUPER_ADMIN') - ) { - return next( - new AppError('You are not allowed to update this calendar', 403) - ); - } - // TODO: update calendar -}; - -exports.deleteCalendar = async (req, res, next) => { - const calendar = await calendar_validators.validateCalendar(req); - // check if user is not admin nor the owner of the calendar - if ( - calendar.createdBy !== req.user.id.toString() || - !req.user.roles.includes('SUPER_ADMIN') - ) { - return next( - new AppError('You are not allowed to delete this calendar', 403) - ); - } - // TODO: delete calendar -}; diff --git a/backend-app/controllers/calendar_controllers/calendar_base_controller.ts b/backend-app/controllers/calendar_controllers/calendar_base_controller.ts new file mode 100644 index 0000000..39af3cc --- /dev/null +++ b/backend-app/controllers/calendar_controllers/calendar_base_controller.ts @@ -0,0 +1,50 @@ +import { IReq, IRes, INext } from '@interfaces/vendors'; +import AppError from '@utils/app_error'; +import * as calendar_validators from './calendar_validators'; + +export const updateCalendar = async ( + req: IReq, + _res: IRes, + next: INext +): Promise => { + try { + const calendar = await calendar_validators.validateCalendar(req); + // check if user is not admin nor the owner of the calendar + if ( + calendar.createdBy !== req.user._id.toString() || + !req.user.roles.includes('ADMIN') || + !req.user.roles.includes('SUPER_ADMIN') + ) { + throw new AppError( + 403, + 'You are not allowed to update this calendar' + ); + } + // TODO: update calendar + } catch (err) { + next(err); + } +}; + +export const deleteCalendar = async ( + req: IReq, + _res: IRes, + next: INext +): Promise => { + try { + const calendar = await calendar_validators.validateCalendar(req); + // check if user is not admin nor the owner of the calendar + if ( + calendar.createdBy !== req.user._id.toString() || + !req.user.roles.includes('SUPER_ADMIN') + ) { + throw new AppError( + 403, + 'You are not allowed to delete this calendar' + ); + } + // TODO: delete calendar + } catch (err) { + next(err); + } +}; diff --git a/backend-app/controllers/calendar_controllers/calendar_validators.js b/backend-app/controllers/calendar_controllers/calendar_validators.js deleted file mode 100644 index 2320287..0000000 --- a/backend-app/controllers/calendar_controllers/calendar_validators.js +++ /dev/null @@ -1,13 +0,0 @@ -const calendarModel = require('../../models/calendar/calendar_model'); - -exports.validateCalendar = async function validateCalendar(req) { - const calendarid = req.params.calendarid; - if (!calendarid) { - throw new AppError('Calendar id is required', 400); - } - const calendar = await calendarModel.findById(calendarid); - if (!calendar) { - throw new AppError('Calendar not found with that id', 404); - } - return calendar; -}; diff --git a/backend-app/controllers/calendar_controllers/calendar_validators.ts b/backend-app/controllers/calendar_controllers/calendar_validators.ts new file mode 100644 index 0000000..ed54b44 --- /dev/null +++ b/backend-app/controllers/calendar_controllers/calendar_validators.ts @@ -0,0 +1,15 @@ +import { Request } from 'express'; +import AppError from '@utils/app_error'; +import Calendar from '@models/calendar/calendar_model'; + +export async function validateCalendar(req: Request) { + const calendarid = req.params.calendarid; + if (!calendarid) { + throw new AppError(400, 'Calendar id is required'); + } + const calendar = await Calendar.findById(calendarid); + if (!calendar) { + throw new AppError(404, 'Calendar not found with that id'); + } + return calendar; +} diff --git a/backend-app/controllers/calendar_controllers/participents_controller.js b/backend-app/controllers/calendar_controllers/participents_controller.js deleted file mode 100644 index 6c4d90e..0000000 --- a/backend-app/controllers/calendar_controllers/participents_controller.js +++ /dev/null @@ -1,63 +0,0 @@ -const AppError = require('../../utils/app_error'); -const validator = require('validator'); -const calendar_validators = require('./calendar_validators'); - -exports.inviteUsersByEmail = async (req, res) => { - // check if calendar exists - const calendar = await calendar_validators.validateCalendar(req); - // check if user is the calendar owner - const userid = req.user._id; - if (calendar.createdBy.toString() !== userid.toString()) { - // check if user is a participant and the calendar is shareable - if (!calendar.participants.includes(userid)) - throw new AppError( - 'You do not have permission to invite users to this calendar', - 403 - ); - if (!calendar.isShareAble) { - throw new AppError('This calendar is not shareable', 403); - } - } - // get emails from request body - const emails = req.body.emails; - if (!emails) { - throw new AppError('Emails are required', 400); - } - // check if emails are valid - const validEmails = []; - const invalidEmails = []; - emails.forEach((email) => { - if (validator.isEmail(email)) { - validEmails.push(email); - } else { - invalidEmails.push(email); - } - }); - // TODO: send emails to valid emails - res.status(200).json({ - status: 'success', - validEmails, - invalidEmails, - }); -}; - -exports.removeCalendarParticipants = async (req, res) => { - const calendar = await calendar_validators.validateCalendar(req); - const userid = req.user._id; - // check if user is the calendar owner - if (calendar.owner.toString() === !userid.toString()) { - throw new AppError('You are not the owner of this calendar', 403); - } - // get list of participants to remove from calendar - const listOfParticipants = req.body.participants; - // remove users from list of participants in calendar - calendar.participants = listOfParticipants.filter( - (participant) => !calendar.participants.includes(participant) - ); - // save calendar - await calendar.save(); - res.status(200).json({ - status: 'success', - calendar, - }); -}; diff --git a/backend-app/controllers/calendar_controllers/participents_controller.ts b/backend-app/controllers/calendar_controllers/participents_controller.ts new file mode 100644 index 0000000..86b9f4f --- /dev/null +++ b/backend-app/controllers/calendar_controllers/participents_controller.ts @@ -0,0 +1,72 @@ +import { INext, IReq, IRes } from '@interfaces/vendors'; +import AppError from '@utils/app_error'; +import validator from 'validator'; +import * as calendar_validators from './calendar_validators'; +import { ObjectId } from 'mongoose'; + +export const inviteUsersByEmail = async (req: IReq, res: IRes, next: INext) => { + try { + // check if calendar exists + const calendar = await calendar_validators.validateCalendar(req); + // check if user is the calendar owner + if (calendar.createdBy.toString() !== req.user._id.toString()) { + // check if user is a participant and the calendar is shareable + if (!calendar.participants.includes(req.user._id)) + throw new AppError( + 403, + 'You do not have permission to invite users to this calendar' + ); + if (!calendar.isShareAble) + throw new AppError(403, 'This calendar is not shareable'); + } + // get emails from request body + const emails = req.body.emails; + if (!emails) { + throw new AppError(400, 'Emails are required'); + } + // check if emails are valid + const validEmails: string[] = []; + const invalidEmails: string[] = []; + emails.forEach((email: string) => { + if (validator.isEmail(email)) { + validEmails.push(email); + } else { + invalidEmails.push(email); + } + }); + // TODO: send emails to valid emails + res.status(200).json({ + validEmails, + invalidEmails, + }); + } catch (err) { + next(err); + } +}; + +export const removeCalendarParticipants = async ( + req: IReq, + res: IRes, + next: INext +) => { + try { + const calendar = await calendar_validators.validateCalendar(req); + // check if user is the calendar owner + if (calendar.createdBy.toString() !== req.user._id.toString()) { + throw new AppError(403, 'You are not the owner of this calendar'); + } + // get list of participants to remove from calendar + const listOfParticipants: ObjectId[] = req.body.participants; + // remove users from list of participants in calendar + calendar.participants = calendar.participants.filter( + (participant: ObjectId) => !listOfParticipants.includes(participant) + ); + // save calendar + await calendar.save(); + res.status(200).json({ + calendar, + }); + } catch (err) { + next(err); + } +}; diff --git a/backend-app/controllers/tryingtsoa.ts b/backend-app/controllers/tryingtsoa.ts new file mode 100644 index 0000000..0e01b2d --- /dev/null +++ b/backend-app/controllers/tryingtsoa.ts @@ -0,0 +1,61 @@ +// src/users/usersController.ts +// import { IUser } from '@interfaces/models/i_user'; +import { Controller, Route } from 'tsoa'; +import { Body, Post, Query, Response, Path, Middlewares } from '@tsoa/runtime'; +import { Response as i_res } from 'express'; +export interface IUser { + /** + * @isString + */ + name: string; + email: string; + address?: string; + password?: string; + authorities: string[]; + restrictions: string[]; + roles: string[]; + active: boolean; + activationKey?: string; + accessRestricted: boolean; + githubOauthAccessToken?: string; + resetKey?: string; + createdAt: Date; + updatedAt: Date; + deleted: boolean; + deletedBy?: string; + deletedAt?: Date; + createdBy?: string; + updatedBy?: string; +} + +interface ValidateErrorJSON { + message: 'Validation failed'; + details: { [name: string]: unknown }; +} + +function customMiddleware(req: Request, res: i_res, next: any) { + // Perform any necessary operations or modifications + next(); +} + +@Route('users') +export class UsersController extends Controller { + /** + * Retrieves the details of an existing user. + * Supply the unique user ID from either and receive corresponding user details. + */ + // @SuccessResponse('201', 'Created') + // // not found response + @Response(404, 'Not Found') + @Post('{userId}') + @Middlewares(customMiddleware) + public getUser( + @Path() userId: number, + @Query() name?: string, + @Body() body?: IUser + ): Object { + // return new UsersService().get(userId, name); + return { userId, name }; + } + // @SuccessResponse('201', 'Created'); +} diff --git a/backend-app/controllers/users_controllers/admin_controller.js b/backend-app/controllers/users_controllers/admin_controller.ts similarity index 51% rename from backend-app/controllers/users_controllers/admin_controller.js rename to backend-app/controllers/users_controllers/admin_controller.ts index b888229..5595c0b 100644 --- a/backend-app/controllers/users_controllers/admin_controller.js +++ b/backend-app/controllers/users_controllers/admin_controller.ts @@ -1,26 +1,23 @@ -const userModel = require('../../models/user/user_model'); -const Actions = require('../../constants/actions'); -const validateActions = require('../../utils/authorization/validate_actions'); -const Role = require('../../utils/authorization/role/role'); -const AppError = require('../../utils/app_error'); -const role = new Role(); +import { IReq, IRes, INext } from '@interfaces/vendors'; +import USER from '@models/user/user_model'; +import Role from '@utils/authorization/roles/role'; +import AppError from '@utils/app_error'; +import validateActions from '@utils/authorization/validate_actions'; -exports.addAdmin = async (req, res, next) => { +export const addAdmin = async (req: IReq, res: IRes, next: INext) => { try { - const Roles = await role.getRoles(); + const Roles = await Role.getRoles(); const { userId } = req.params; - const user = await userModel.findById(userId); - if (!user) - throw new AppError(404, 'fail', 'No user found with this id'); - if (req.user._id?.toString() === userId?.toString()) + const user = await USER.findById(userId); + if (!user) throw new AppError(404, 'No user found with this id'); + if (!Roles.ADMIN) throw new AppError( - 400, - 'fail', - 'You cannot make yourself an admin' + 500, + 'Error in base roles, please contact an admin' ); - if (user.roles?.includes(Roles.ADMIN.type)) - throw new AppError(400, 'fail', 'User is already an admin'); - user.roles?.push(Roles.ADMIN.type); + if (user.roles?.includes(Roles.ADMIN.name)) + throw new AppError(400, 'User is already an admin'); + user.roles?.push(Roles.ADMIN.name); const existingAuthorities = user.authorities; const existingRestrictions = user.restrictions; user.authorities = Array.from( @@ -38,22 +35,22 @@ exports.addAdmin = async (req, res, next) => { } }; -exports.removeAdmin = async (req, res, next) => { +export const removeAdmin = async (req: IReq, res: IRes, next: INext) => { try { - const Roles = await role.getRoles(); + const Roles = await Role.getRoles(); const { userId } = req.params; - const user = await userModel.findById(userId); - if (!user) - throw new AppError(404, 'fail', 'No user found with this id'); - if (req.user._id?.toString() === userId?.toString()) + const user = await USER.findById(userId); + if (!user) throw new AppError(404, 'No user found with this id'); + if (!Roles.ADMIN || !Roles.USER) throw new AppError( - 400, - 'fail', - 'You cannot remove yourself as an admin' + 500, + 'Error in base roles, please contact an admin' ); - if (!user.roles?.includes(Roles.ADMIN.type)) - throw new AppError(400, 'fail', 'User is not an admin'); - user.roles = user.roles.filter((role) => role !== Roles.ADMIN.type); + if (req.user._id?.toString() === userId?.toString()) + throw new AppError(400, 'You cannot remove yourself as an admin'); + if (!user.roles?.includes(Roles.ADMIN.name)) + throw new AppError(400, 'User is not an admin'); + user.roles = user.roles.filter((role) => role !== Roles.ADMIN.name); user.authorities = Roles.USER.authorities; user.restrictions = Roles.USER.restrictions; await user.save(); @@ -65,22 +62,17 @@ exports.removeAdmin = async (req, res, next) => { } }; -exports.addSuperAdmin = async (req, res, next) => { +export const addSuperAdmin = async (req: IReq, res: IRes, next: INext) => { try { - const Roles = await role.getRoles(); + const Roles = await Role.getRoles(); const { userId } = req.params; - const user = await userModel.findById(userId); - if (!user) - throw new AppError(404, 'fail', 'No user found with this id'); + const user = await USER.findById(userId); + if (!user) throw new AppError(404, 'No user found with this id'); if (req.user._id?.toString() === userId?.toString()) - throw new AppError( - 400, - 'fail', - 'You cannot make yourself a super admin' - ); - if (user.roles?.includes(Roles.SUPER_ADMIN.type)) - throw new AppError(400, 'fail', 'User is already a super admin'); - user.roles?.push(Roles.SUPER_ADMIN.type); + throw new AppError(400, 'You cannot make yourself a super admin'); + if (user.roles?.includes(Roles.SUPER_ADMIN.name)) + throw new AppError(400, 'User is already a super admin'); + user.roles?.push(Roles.SUPER_ADMIN.name); const existingRestrictions = user.restrictions; user.authorities = Roles.SUPER_ADMIN.authorities; user.restrictions = Array.from( @@ -97,23 +89,22 @@ exports.addSuperAdmin = async (req, res, next) => { next(err); } }; -exports.removeSuperAdmin = async (req, res, next) => { + +export const removeSuperAdmin = async (req: IReq, res: IRes, next: INext) => { const { userId } = req.params; try { - const Roles = await role.getRoles(); - const user = await userModel.findById(userId); - if (!user) - throw new AppError(404, 'fail', 'No user found with this id'); + const Roles = await Role.getRoles(); + const user = await USER.findById(userId); + if (!user) throw new AppError(404, 'No user found with this id'); if (req.user._id?.toString() === userId?.toString()) throw new AppError( 400, - 'fail', 'You cannot remove yourself as a super admin' ); - if (!user.roles?.includes(Roles.SUPER_ADMIN.type)) - throw new AppError(400, 'fail', 'User is not a super admin'); + if (!user.roles?.includes(Roles.SUPER_ADMIN.name)) + throw new AppError(400, 'User is not a super admin'); user.roles = user.roles.filter( - (role) => role !== Roles.SUPER_ADMIN.type + (role) => role !== Roles.SUPER_ADMIN.name ); user.authorities = Roles.ADMIN.authorities; user.restrictions = Roles.ADMIN.restrictions; @@ -125,34 +116,35 @@ exports.removeSuperAdmin = async (req, res, next) => { next(err); } }; -exports.authorizeOrRestrict = async (req, res, next) => { + +export const authorizeOrRestrict = async ( + req: IReq, + res: IRes, + next: INext +) => { try { const { authorities, restrictions } = req.body; const { userId } = req.params; if (!validateActions(authorities)) throw new AppError( 400, - 'fail', 'One or many actions are invalid in the authorities array' ); if (!validateActions(restrictions)) throw new AppError( 400, - 'fail', 'One or many actions are invalid in the restrictions array' ); if (req.user._id?.toString() === userId?.toString()) throw new AppError( 400, - 'fail', 'You cannot change your own authorities or restrictions' ); - const user = await userModel.findById(userId); - if (!user) - throw new AppError(404, 'fail', 'No user found with this id'); + const user = await USER.findById(userId); + if (!user) throw new AppError(404, 'No user found with this id'); // if the user is a super admin, he can't be restricted if (user.roles?.includes('SUPER_ADMIN')) - throw new AppError(400, 'fail', 'User is a super admin'); + throw new AppError(400, 'User is a super admin'); const existingAuthorities = user.authorities; const existingRestrictions = user.restrictions; user.authorities = Array.from( @@ -169,21 +161,21 @@ exports.authorizeOrRestrict = async (req, res, next) => { next(err); } }; -exports.banUser = async (req, res, next) => { + +export const banUser = async (req: IReq, res: IRes, next: INext) => { const { userId } = req.params; try { - const Roles = await role.getRoles(); - const user = await userModel.findById(userId); - if (!user) - throw new AppError(404, 'fail', 'No user found with this id'); + const Roles = await Role.getRoles(); + const user = await USER.findById(userId); + if (!user) throw new AppError(404, 'No user found with this id'); if (req.user._id?.toString() === userId?.toString()) - throw new AppError(400, 'fail', 'You cannot ban yourself'); + throw new AppError(400, 'You cannot ban yourself'); if (user.accessRestricted) - throw new AppError(400, 'fail', 'User is already banned'); - if (user.roles?.includes(Roles.SUPER_ADMIN.type)) - throw new AppError(400, 'fail', 'You cannot ban a super admin'); - if (user.roles?.includes(Roles.ADMIN.type)) - throw new AppError(400, 'fail', 'You cannot ban an admin'); + throw new AppError(400, 'User is already banned'); + if (user.roles?.includes(Roles.SUPER_ADMIN.name)) + throw new AppError(400, 'You cannot ban a super admin'); + if (user.roles?.includes(Roles.ADMIN.name)) + throw new AppError(400, 'You cannot ban an admin'); user.accessRestricted = true; await user.save(); res.status(200).json({ @@ -193,16 +185,16 @@ exports.banUser = async (req, res, next) => { next(err); } }; -exports.unbanUser = async (req, res, next) => { + +export const unbanUser = async (req: IReq, res: IRes, next: INext) => { const { userId } = req.params; try { - const user = await userModel.findById(userId); - if (!user) - throw new AppError(404, 'fail', 'No user found with this id'); + const user = await USER.findById(userId); + if (!user) throw new AppError(404, 'No user found with this id'); if (req.user._id?.toString() === userId?.toString()) - throw new AppError(400, 'fail', 'You cannot unban yourself'); + throw new AppError(400, 'You cannot unban yourself'); if (!user.accessRestricted) - throw new AppError(400, 'fail', 'User is not banned'); + throw new AppError(400, 'User is not banned'); user.accessRestricted = false; await user.save(); res.status(200).json({ @@ -212,12 +204,13 @@ exports.unbanUser = async (req, res, next) => { next(err); } }; -exports.createRole = async (req, res, next) => { + +export const createRole = async (req: IReq, res: IRes, next: INext) => { const { name, authorities, restrictions } = req.body; try { - if (await role.getRoleByName(name)) - throw new AppError(400, 'fail', 'Role already exists'); - const createdRole = await role.createRole( + if (await Role.getRoleByName(name)) + throw new AppError(400, 'Role already exists'); + const createdRole = await Role.createRole( name, authorities, restrictions @@ -230,9 +223,10 @@ exports.createRole = async (req, res, next) => { next(err); } }; -exports.getRoles = async (req, res, next) => { + +export const getRoles = async (_req: IReq, res: IRes, next: INext) => { try { - const roles = await role.getRoles(); + const roles = await Role.getRoles(); res.status(200).json({ message: 'Roles retrieved', data: roles, @@ -241,10 +235,11 @@ exports.getRoles = async (req, res, next) => { next(err); } }; -exports.getRole = async (req, res, next) => { + +export const getRole = async (req: IReq, res: IRes, next: INext) => { const { name } = req.params; try { - const singleRole = await role.getRoleByName(name); + const singleRole = await Role.getRoleByName(name as string); res.status(200).json({ message: 'Role retrieved', data: singleRole, @@ -253,10 +248,11 @@ exports.getRole = async (req, res, next) => { next(err); } }; -exports.deleteRole = async (req, res, next) => { + +export const deleteRole = async (req: IReq, res: IRes, next: INext) => { const { name } = req.params; try { - const deletedRole = await role.deleteRoleByName(name); + const deletedRole = await Role.deleteRoleByName(name as string); res.status(200).json({ message: 'Role deleted', data: deletedRole, @@ -265,12 +261,13 @@ exports.deleteRole = async (req, res, next) => { next(err); } }; -exports.updateRole = async (req, res, next) => { + +export const updateRole = async (req: IReq, res: IRes, next: INext) => { const { name } = req.params; const { authorities, restrictions } = req.body; try { - const updatedRole = await role.updateRoleByName( - name, + const updatedRole = await Role.updateRoleByName( + name as string, authorities, restrictions ); @@ -282,23 +279,22 @@ exports.updateRole = async (req, res, next) => { next(err); } }; -exports.assignRoleToUser = async (req, res, next) => { + +export const assignRoleToUser = async (req: IReq, res: IRes, next: INext) => { const { userId, name } = req.params; try { - const user = await userModel.findById(userId); - const Role = await role.getRoleByName(name); - if (!user) - throw new AppError(404, 'fail', 'No user found with this id'); - if (!Role) - throw new AppError(404, 'fail', 'No role found with this name'); - if (user.roles.includes(Role.type)) - throw new AppError(400, 'fail', 'User already has this role'); - user.roles.push(Role.type); + const user = await USER.findById(userId); + const role = await Role.getRoleByName(name as string); + if (!user) throw new AppError(404, 'No user found with this id'); + if (!role) throw new AppError(404, 'No role found with this name'); + if (user.roles.includes(role.name)) + throw new AppError(400, 'User already has this role'); + user.roles.push(role.name); user.authorities = Array.from( - new Set([...Role.authorities, ...user.authorities]) + new Set([...role.authorities, ...user.authorities]) ); user.restrictions = Array.from( - new Set([...Role.restrictions, ...user.restrictions]) + new Set([...role.restrictions, ...user.restrictions]) ); await user.save(); res.status(200).json({ @@ -308,23 +304,22 @@ exports.assignRoleToUser = async (req, res, next) => { next(err); } }; -exports.removeRoleFromUser = async (req, res, next) => { + +export const removeRoleFromUser = async (req: IReq, res: IRes, next: INext) => { const { userId, name } = req.params; try { - const Role = await role.getRoleByName(name); - if (!Role) - throw new AppError(404, 'fail', 'No role found with this name'); - const user = await userModel.findById(userId); - if (!user) - throw new AppError(404, 'fail', 'No user found with this id'); - if (!user.roles.includes(Role.type)) - throw new AppError(400, 'fail', 'User does not have this role'); - user.roles = user.roles.filter((role) => role !== Role.type); + const role = await Role.getRoleByName(name as string); + if (!role) throw new AppError(404, 'No role found with this name'); + const user = await USER.findById(userId); + if (!user) throw new AppError(404, 'No user found with this id'); + if (!user.roles.includes(role.name)) + throw new AppError(400, 'User does not have this role'); + user.roles = user.roles.filter((_role) => _role !== role.name); user.authorities = user.authorities.filter( - (authority) => !Role.authorities.includes(authority) + (authority) => !role.authorities.includes(authority) ); user.restrictions = user.restrictions.filter( - (restriction) => !Role.restrictions.includes(restriction) + (restriction) => !role.restrictions.includes(restriction) ); await user.save(); res.status(200).json({ diff --git a/backend-app/controllers/users_controllers/user_controller.js b/backend-app/controllers/users_controllers/user_controller.js deleted file mode 100644 index a07c5ed..0000000 --- a/backend-app/controllers/users_controllers/user_controller.js +++ /dev/null @@ -1,88 +0,0 @@ -const User = require('../../models/user/user_model'); -const base = require('../base_controller'); -const AppError = require('../../utils/app_error'); -const sanitizeRequestBody = require('../../utils/sanitize_request_body'); - -exports.getMe = (req, res) => { - // return data of the current user - res.status(200).json({ - status: 'success', - data: req.user, - }); -}; - -exports.deleteMe = async (req, res, next) => { - try { - await User.findByIdAndUpdate(req.user.id, { - deleted: true, - deletedAt: Date.now(), - deletedBy: req.user.id, - }); - - res.status(204).json({ - data: null, - }); - } catch (error) { - next(error); - } -}; - -exports.updateMe = async (req, res, next) => { - try { - // 1) Create error if user POSTs password data - if (req.body.password || req.body.passwordConfirm) { - return next( - new AppError( - 400, - 'fail', - 'This route is not for password updates. Please use /updateMyPassword' - ) - ); - } - // create error if user tries to update role - if (req.body.roles) { - return next( - new AppError( - 400, - 'fail', - 'This route is not for role updates. Please use /updateRole' - ) - ); - } - // 2) Filtered out unwanted fields names that are not allowed to be updated - const filteredfields = Object.keys(req.body).filter( - (el) => el !== 'email' - ); - const filteredBody = {}; - filteredfields.forEach((el) => { - filteredBody[el] = req.body[el]; - }); - - // validate the request body - const sanitizedBody = sanitizeRequestBody(User.schema, filteredBody); - - // 3) Update user document - const doc = await User.findByIdAndUpdate(req.user.id, sanitizedBody, { - new: true, - runValidators: true, - }); - if (!doc) { - return next( - new AppError(404, 'fail', 'No document found with that id') - ); - } - - res.status(200).json({ - doc, - }); - } catch (error) { - next(error); - } -}; - -exports.getAllUsers = base.getAll(User); -exports.getUser = base.getOne(User); - -// Don't update password on this -exports.updateUser = base.updateOne(User); -exports.deleteUser = base.deleteOne(User); diff --git a/backend-app/controllers/users_controllers/user_controller.ts b/backend-app/controllers/users_controllers/user_controller.ts new file mode 100644 index 0000000..f9efdcb --- /dev/null +++ b/backend-app/controllers/users_controllers/user_controller.ts @@ -0,0 +1,72 @@ +import User from '@models/user/user_model'; +import * as base from '../base_controller'; +import AppError from '@utils/app_error'; +import { INext, IReq, IRes } from '@interfaces/vendors'; + +export const getMe = (req: IReq, res: IRes) => { + // return data of the current user + res.status(200).json({ + user: req.user, + }); +}; + +export const deleteMe = async (req: IReq, res: IRes, next: INext) => { + try { + await User.findByIdAndUpdate(req.user._id, { + deleted: true, + deletedAt: Date.now(), + deletedBy: req.user._id, + }); + + res.status(204).json({ + data: null, + }); + } catch (error) { + next(error); + } +}; + +export const updateMe = async (req: IReq, res: IRes, next: INext) => { + try { + // 1) Create error if user POSTs password data + if (req.body.password || req.body.passwordConfirm) { + throw new AppError( + 400, + 'This route is not for password updates. Please use /updateMyPassword' + ); + } + // create error if user tries to update role + if (req.body.roles) { + throw new AppError( + 400, + 'This route is not for role updates. Please use /updateRole' + ); + } + // 2) Filtered out unwanted fields names that are not allowed to be updated + const payload = { + name: req.body.name, + email: req.body.email, + }; + // 3) Update user document + const doc = await User.findByIdAndUpdate(req.user._id, payload, { + new: true, + runValidators: true, + }); + if (!doc) { + return next(new AppError(404, 'No document found with that id')); + } + + res.status(200).json({ + doc, + }); + } catch (error) { + next(error); + } +}; + +export const getAllUsers = base.getAll(User); +export const getUser = base.getOne(User); + +// Don't update password on this +export const updateUser = base.updateOne(User); +export const deleteUser = base.deleteOne(User); diff --git a/backend-app/globalConfig.json b/backend-app/globalConfig.json deleted file mode 100644 index 7e6abfe..0000000 --- a/backend-app/globalConfig.json +++ /dev/null @@ -1 +0,0 @@ -{ "mongoUri": "mongodb://127.0.0.1:58466/" } diff --git a/backend-app/interfaces/github_repo.ts b/backend-app/interfaces/github_repo.ts new file mode 100644 index 0000000..684c078 --- /dev/null +++ b/backend-app/interfaces/github_repo.ts @@ -0,0 +1,12 @@ +export default interface Repository { + id: number; + name: string; + full_name: string; + description: string; + isFork: boolean; + language: string; + license: string | null; + openedIssuesCount: number; + repoCreatedAt: string; + url: string; +} diff --git a/backend-app/interfaces/models/i_calendar.ts b/backend-app/interfaces/models/i_calendar.ts new file mode 100644 index 0000000..7383fce --- /dev/null +++ b/backend-app/interfaces/models/i_calendar.ts @@ -0,0 +1,20 @@ +import mongoose from 'mongoose'; + +export interface ICalendar extends Document { + Name: string; + Type: string; + isPublic: boolean; + isShareAble: boolean; + participants: mongoose.Schema.Types.ObjectId[]; + events: mongoose.Schema.Types.ObjectId[]; + description?: string; + accessCode?: string; + tags: string[]; + allowedUsers: mongoose.Schema.Types.ObjectId[]; + deniedUsers: mongoose.Schema.Types.ObjectId[]; + deleted: boolean; + deletedBy?: string; + deletedAt?: Date; + createdBy?: string; + updatedBy?: string; +} diff --git a/backend-app/interfaces/models/i_event.ts b/backend-app/interfaces/models/i_event.ts new file mode 100644 index 0000000..516751b --- /dev/null +++ b/backend-app/interfaces/models/i_event.ts @@ -0,0 +1,21 @@ +import { Document } from 'mongoose'; + +export interface IEvent extends Document { + name: string; + description?: string; + location?: string; + startDate: Date; + endDate: Date; + startTime: string; + endTime: string; + color: string; + recurring?: boolean; + recurringType?: 'Daily' | 'Weekly' | 'Monthly' | 'Yearly'; + recurringEndDate?: Date; + reminder?: Date; + deleted: boolean; + deletedBy?: string; + deletedAt?: Date; + createdBy?: string; + updatedBy?: string; +} diff --git a/backend-app/interfaces/models/i_role.ts b/backend-app/interfaces/models/i_role.ts new file mode 100644 index 0000000..e4ceb74 --- /dev/null +++ b/backend-app/interfaces/models/i_role.ts @@ -0,0 +1,12 @@ +import { Document } from 'mongoose'; + +export interface IRole extends Document { + name: string; + authorities: string[]; + restrictions: string[]; + deleted: boolean; + deletedBy?: string; + deletedAt?: Date; + createdBy?: string; + updatedBy?: string; +} diff --git a/backend-app/interfaces/models/i_user.ts b/backend-app/interfaces/models/i_user.ts new file mode 100644 index 0000000..429b309 --- /dev/null +++ b/backend-app/interfaces/models/i_user.ts @@ -0,0 +1,32 @@ +import { ObjectId } from 'mongoose'; +import { Document } from 'mongoose'; + +export interface IUser extends Document { + _id: ObjectId; + name: string; + email: string; + address?: string; + password?: string; + authorities: string[]; + restrictions: string[]; + roles: string[]; + active: boolean; + activationKey?: string; + accessRestricted: boolean; + githubOauthAccessToken?: string; + resetKey?: string; + createdAt: Date; + updatedAt: Date; + deleted: boolean; + deletedBy?: string; + deletedAt?: Date; + createdBy?: string; + updatedBy?: string; + correctPassword( + typedPassword: string, + originalPassword: string + ): Promise; + isAuthorizedTo(action: string[]): boolean; + isRestrictedFrom(action: string[]): boolean; + generateResetKey(): string; +} diff --git a/backend-app/interfaces/vendors.ts b/backend-app/interfaces/vendors.ts new file mode 100644 index 0000000..889afdf --- /dev/null +++ b/backend-app/interfaces/vendors.ts @@ -0,0 +1,23 @@ +import { Request } from 'express'; + +export interface IReq extends Request { + user: { + _id: ObjectId; + name?: string; + email: string; + roles?: string[]; + authorities?: string[]; + restrictions?: string[]; + active: boolean; + githubOauthAccessToken?: string; + }; +} + +import { Response } from 'express'; + +export interface IRes extends Response {} + +import { NextFunction } from 'express'; +import { ObjectId } from 'mongoose'; + +export interface INext extends NextFunction {} diff --git a/backend-app/jest.config.js b/backend-app/jest.config.js deleted file mode 100644 index 9ffdb90..0000000 --- a/backend-app/jest.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - globalSetup: './tests/setup.js', - globalTeardown: './tests/teardown.js', - setupFilesAfterEnv: ['./tests/db_config.js'], - bail: true, -}; diff --git a/backend-app/middlewares/api_version_controll.js b/backend-app/middlewares/api_version_controll.js deleted file mode 100644 index 03577d4..0000000 --- a/backend-app/middlewares/api_version_controll.js +++ /dev/null @@ -1,19 +0,0 @@ -const { API_VERSION } = require('../config/app_config'); - -/** - * Middleware to set default API version in the request URL if not provided. - * If the API version is missing, it will be set to 'v3' by default. - * @param {Object} req - Express request object. - * @param {Object} res - Express response object. - * @param {Function} next - Express next function to pass control to the next middleware or route handler. - */ -const handleAPIVersion = (req, res, next) => { - req.version = req.headers['accept-version']; - if (!req.version) { - req.version = API_VERSION; - req.headers['accept-version'] = API_VERSION; - } - next(); -}; - -module.exports = handleAPIVersion; diff --git a/backend-app/middlewares/api_version_controll.ts b/backend-app/middlewares/api_version_controll.ts new file mode 100644 index 0000000..4ca2cec --- /dev/null +++ b/backend-app/middlewares/api_version_controll.ts @@ -0,0 +1,18 @@ +import { Request, Response, NextFunction } from 'express'; +import { API_VERSION } from '@config/app_config'; + +/** + * Middleware to set default API version in the request URL if not provided. + * If the API version is missing, it will be set to 'v3' by default. + * @param {Request} req - Express request object. + * @param {Response} res - Express response object. + * @param {NextFunction} next - Express next function to pass control to the next middleware or route handler. + */ +const handleAPIVersion = (req: Request, _res: Response, next: NextFunction) => { + if (!req.headers['accept-version']) { + req.headers['accept-version'] = API_VERSION; + } + next(); +}; + +export default handleAPIVersion; diff --git a/backend-app/middlewares/authorization.js b/backend-app/middlewares/authorization.js deleted file mode 100644 index 126053f..0000000 --- a/backend-app/middlewares/authorization.js +++ /dev/null @@ -1,54 +0,0 @@ -const AppError = require('../utils/app_error'); -const { Request, Response, NextFunction } = require('express'); -const Actions = require('../constants/actions'); - -/** - * - * @param {{authorities:string[]}} user - * @param {string[]} actions - * @returns {boolean} - */ -const hasAuthority = (user, actions) => - actions.every((action) => user.authorities.includes(action)); - -/** - * - * @param {{restrictions:string[]}} user - * @param {string[]} actions - * @returns {boolean} - */ -const isRestricted = (user, actions) => - actions.every((action) => !user.restrictions.includes(action)) - ? false - : true; - -/** - * @param {...string} roles - * @returns {(...actions:string[])=>(req:Request,res:Response,next:NextFunction)=>void} - */ -const restrictTo = - (...actions) => - (req, res, next) => { - if (hasAuthority(req.user, actions)) { - if (!isRestricted(req.user, actions)) next(); - else - next( - new AppError( - 403, - 'fail', - 'You are restricted from performing this action, contact the admin for more information' - ) - ); - } else - next( - new AppError( - 403, - 'fail', - 'You do not have permission to perform this action' - ) - ); - }; - -module.exports = { - restrictTo, -}; diff --git a/backend-app/middlewares/authorization.ts b/backend-app/middlewares/authorization.ts new file mode 100644 index 0000000..1fbb403 --- /dev/null +++ b/backend-app/middlewares/authorization.ts @@ -0,0 +1,40 @@ +import AppError from '@utils/app_error'; +import { INext, IReq, IRes } from '@interfaces/vendors'; +import User from '@models/user/user_model'; + +const restrictTo = + (...actions: string[]) => + async (req: IReq, res: IRes, next: INext): Promise => { + try { + // get the user by id + const user = await User.findById(req.user._id); + if (!user) + throw new AppError( + 401, + 'The user belonging to this token does no longer exist' + ); + if (user.isAuthorizedTo(actions)) { + if (!user.isRestrictedFrom(actions)) { + next(); + } else { + next( + new AppError( + 403, + 'You are restricted from performing this action, contact the admin for more information' + ) + ); + } + } else { + next( + new AppError( + 403, + 'You do not have permission to perform this action ; required permissions: ' + + actions + ) + ); + } + } catch (error) { + next(error); + } + }; +export default restrictTo; diff --git a/backend-app/middlewares/global_error_handler.js b/backend-app/middlewares/global_error_handler.js deleted file mode 100644 index baa38e7..0000000 --- a/backend-app/middlewares/global_error_handler.js +++ /dev/null @@ -1,64 +0,0 @@ -const httpStatus = require('http-status-codes'); -const { CURRENT_ENV } = require('../config/app_config'); -const AppError = require('../utils/app_error'); -require('../utils/logger'); - -/** - * Error handling middleware - * @param {Error} err - The error object - * @param {Object} req - The Express request object - * @param {Object} res - The Express response object - * @param {Function} next - The next middleware function - * @returns {void} - * Express automatically knows that this entire function is an error handling middleware by specifying 4 parameters - */ -module.exports = (err, req, res, next) => { - // Set default values if not provided - err.path = err.path || req.path; - err.statusCode = err.statusCode || 500; - err.message = err.message || httpStatus.getStatusText(err.statusCode); - - // Handle duplicate key errors - if (err.code === 11000) { - Object.keys(err.keyValue).forEach((key) => { - err.message = `Duplicate value for the field: [${key}]. Please use another value!`; - }); - err.statusCode = 409; - } - - // Handle validation errors - if (err.name === 'ValidationError') { - err = new AppError(400, 'fail', err.message); - } - - // Determine the description based on error status code and environment - let description; - if (err.statusCode >= 500) { - if (CURRENT_ENV === 'development') { - description = err.message; - } else { - description = - "We're sorry, something went wrong. Please try again later." + - err; - } - } else { - description = err.message; - } - - // Construct the response object - const response = { - status: err.statusCode, - title: httpStatus.getStatusText(err.statusCode), - details: { - ...(err.path && { path: err.path }), - description, - ...(CURRENT_ENV === 'development' && { - error: - 'Do not forget to remove this in production!\n' + err.stack, - }), - }, - }; - - // Send the response - res.status(err.statusCode).json(response); -}; diff --git a/backend-app/middlewares/global_error_handler.ts b/backend-app/middlewares/global_error_handler.ts new file mode 100644 index 0000000..1321df7 --- /dev/null +++ b/backend-app/middlewares/global_error_handler.ts @@ -0,0 +1,87 @@ +import { NextFunction, Request, Response } from 'express'; +import httpStatus from 'http-status-codes'; +import { CURRENT_ENV } from '@config/app_config'; +import AppError from '@utils/app_error'; + +/** + * Error handling middleware + * @param {Error} err - The error object + * @param {Object} req - The Express request object + * @param {Object} res - The Express response object + * @param {Function} next - The next middleware function + * @returns {void} + * Express automatically knows that this entire function is an error handling middleware by specifying 4 parameters + */ +const errorHandler = ( + err: Error, + req: Request, + res: Response, + _next: NextFunction +): void => { + // Set default values if not provided + (err as any).path = (err as any).path || req.path; + (err as any).statusCode = (err as any).statusCode || 500; + (err as any).message = + (err as any).message || + httpStatus.getStatusText((err as any).statusCode); + + // Handle duplicate key errors + if ((err as any).code === 11000) { + Object.keys((err as any).keyValue).forEach((key) => { + ( + err as any + ).message = `Duplicate value for the field: [${key}]. Please use another value!`; + }); + (err as any).statusCode = 409; + } + + // Handle validation errors + if ((err as any).name === 'ValidationError') { + err = new AppError(400, (err as any).message); + } + + // Determine the message based on error status code and environment + let message; + if ((err as any).statusCode >= 500) { + if (CURRENT_ENV === 'development') { + message = (err as any).message; + } else { + message = + "We're sorry, something went wrong. Please try again later." + + err; + } + } else { + message = (err as any).message; + } + // tsting : + const stackTrace = (err as any).stack?.split('at '); + const stackTraceObject = stackTrace?.reduce( + (acc: any, line: string, index: number) => { + acc[index + 1] = line; + return acc; + }, + {} + ); + + // Construct the response object + const response = { + status: (err as any).statusCode, + title: httpStatus.getStatusText((err as any).statusCode), + details: { + ...((err as any).path && { path: (err as any).path }), + ...(CURRENT_ENV === 'development' && { + error: { + '0': 'Do not forget to remove this in production!', + ...stackTraceObject, + }, + }), + }, + message, + }; + // logger.debug((err as any).stack); + + // Send the response + res.status((err as any).statusCode).json(response); +}; + +export default errorHandler; diff --git a/backend-app/middlewares/morgan.js b/backend-app/middlewares/morgan.ts similarity index 63% rename from backend-app/middlewares/morgan.js rename to backend-app/middlewares/morgan.ts index 0f7c719..5b5c0ea 100644 --- a/backend-app/middlewares/morgan.js +++ b/backend-app/middlewares/morgan.ts @@ -1,12 +1,13 @@ /** * @description This file contains the morgan middleware for logging requests */ -const morgan = require('morgan'); -const { CURRENT_ENV } = require('../config/app_config'); +import morgan from 'morgan'; +import logger from '@utils/logger'; +import { CURRENT_ENV } from '@config/app_config'; // Create a stream object with a 'write' function that will be used by `morgan` const stream = { - write: (message) => Logger.http(message), + write: (message: string) => logger.http(message), }; // Setup the logger @@ -14,11 +15,12 @@ const Morgan = morgan( ':method :url :status :res[content-length] - :response-time ms', { stream, - skip: (req) => + skip: (req: any) => CURRENT_ENV.toLowerCase() === 'production' || + CURRENT_ENV.toLowerCase() === 'test' || (req.originalUrl && req.originalUrl !== req.url), } ); // Export the logger -module.exports = Morgan; +export default Morgan; diff --git a/backend-app/middlewares/rate_limit.js b/backend-app/middlewares/rate_limit.js deleted file mode 100644 index 0562999..0000000 --- a/backend-app/middlewares/rate_limit.js +++ /dev/null @@ -1,9 +0,0 @@ -const rateLimit = require('express-rate-limit'); -const { RATE_LIMIT_PER_HOUR } = require('../config/app_config'); - -module.exports = rateLimit({ - max: RATE_LIMIT_PER_HOUR, - windowMs: 60 * 60 * 1000, - message: 'Too many requests from this IP, please try again in an hour!', - skip: (req, res) => req.headers.accept === 'text/event-stream', // Ignore SSE requests -}); diff --git a/backend-app/middlewares/rate_limit.ts b/backend-app/middlewares/rate_limit.ts new file mode 100644 index 0000000..ebce032 --- /dev/null +++ b/backend-app/middlewares/rate_limit.ts @@ -0,0 +1,10 @@ +import rateLimit from 'express-rate-limit'; +import { RATE_LIMIT_PER_HOUR } from '@config/app_config'; +import { Request } from 'express'; + +export default rateLimit({ + max: RATE_LIMIT_PER_HOUR, + windowMs: 60 * 60 * 1000, + message: 'Too many requests from this IP, please try again in an hour!', + skip: (req: Request) => req.headers.accept === 'text/event-stream', // Ignore SSE requests +}); diff --git a/backend-app/models/calendar/calendar_model.js b/backend-app/models/calendar/calendar_model.ts similarity index 69% rename from backend-app/models/calendar/calendar_model.js rename to backend-app/models/calendar/calendar_model.ts index 4462b17..b4c5a97 100644 --- a/backend-app/models/calendar/calendar_model.js +++ b/backend-app/models/calendar/calendar_model.ts @@ -1,7 +1,8 @@ -const mongoose = require('mongoose'); -const metaData = require('../constants/meta_data'); +import mongoose, { Schema } from 'mongoose'; +import metaData from '@constants/meta_data'; +import { ICalendar } from '@interfaces/models/i_calendar'; -const calendarSchema = new mongoose.Schema( +const calendarSchema: Schema = new Schema( { Name: { type: String, @@ -11,7 +12,7 @@ const calendarSchema = new mongoose.Schema( type: String, required: [true, 'Please fill your calendar type'], validate: { - validator: function (el) { + validator: function (el: string) { return el === 'Personal' || el === 'Group'; }, }, @@ -27,13 +28,13 @@ const calendarSchema = new mongoose.Schema( }, participants: [ { - type: mongoose.Schema.ObjectId, + type: mongoose.Schema.Types.ObjectId, ref: 'User', }, ], events: [ { - type: mongoose.Schema.ObjectId, + type: mongoose.Schema.Types.ObjectId, ref: 'Event', }, ], @@ -50,13 +51,13 @@ const calendarSchema = new mongoose.Schema( ], allowedUsers: [ { - type: mongoose.Schema.ObjectId, + type: mongoose.Schema.Types.ObjectId, ref: 'User', }, ], deniedUsers: [ { - type: mongoose.Schema.ObjectId, + type: mongoose.Schema.Types.ObjectId, ref: 'User', }, ], @@ -69,6 +70,6 @@ const calendarSchema = new mongoose.Schema( metaData.apply(calendarSchema); -const Calendar = mongoose.model('Calendar', calendarSchema); +const Calendar = mongoose.model('Calendar', calendarSchema); -module.exports = Calendar; +export default Calendar; diff --git a/backend-app/models/calendar/event_model.js b/backend-app/models/calendar/event_model.ts similarity index 73% rename from backend-app/models/calendar/event_model.js rename to backend-app/models/calendar/event_model.ts index 97f0312..35ef957 100644 --- a/backend-app/models/calendar/event_model.js +++ b/backend-app/models/calendar/event_model.ts @@ -1,7 +1,8 @@ -const mongoose = require('mongoose'); -const metaData = require('../constants/meta_data'); +import mongoose, { Schema } from 'mongoose'; +import metaData from '@constants/meta_data'; +import { IEvent } from '@interfaces/models/i_event'; -const eventSchema = new mongoose.Schema({ +const eventSchema: Schema = new Schema({ name: { type: String, required: [true, 'Please fill your event name'], @@ -46,8 +47,8 @@ const eventSchema = new mongoose.Schema({ reminder: { type: Date, validate: { - validator: function (el) { - return el < this.eventStartDate; + validator: function (this: IEvent, el: Date) { + return el < this.startDate; }, }, }, @@ -55,6 +56,6 @@ const eventSchema = new mongoose.Schema({ metaData.apply(eventSchema); -const Event = mongoose.model('Event', eventSchema); +const Event = mongoose.model('Event', eventSchema); -module.exports = Event; +export default Event; diff --git a/backend-app/models/user/role_model.js b/backend-app/models/user/role_model.js deleted file mode 100644 index 6a96aef..0000000 --- a/backend-app/models/user/role_model.js +++ /dev/null @@ -1,50 +0,0 @@ -const mongoose = require('mongoose'); -const Actions = require('../../constants/actions'); -const validator = require('validator'); -const roleSchema = new mongoose.Schema( - { - name: { - type: String, - required: true, - trim: true, - unique: true, - uppercase: true, - validate: { - validator: (value) => { - return value.length > 0; - }, - }, - }, - authorities: [ - { - type: String, - required: true, - default: [], - validate: { - validator: (value) => { - return validator.isIn(value, Object.values(Actions)); - }, - }, - }, - ], - restrictions: [ - { - type: String, - required: true, - default: [], - validate: { - validator: (value) => { - return validator.isIn(value, Object.values(Actions)); - }, - }, - }, - ], - }, - { - timestamps: true, - versionKey: false, - } -); - -const roleModel = mongoose.model('Role', roleSchema); -module.exports = roleModel; diff --git a/backend-app/models/user/role_model.ts b/backend-app/models/user/role_model.ts new file mode 100644 index 0000000..03cd8df --- /dev/null +++ b/backend-app/models/user/role_model.ts @@ -0,0 +1,47 @@ +import mongoose, { Schema } from 'mongoose'; +import Actions from '@constants/actions'; +import validator from 'validator'; +import { IRole } from '@interfaces/models/i_role'; + +const roleSchema: Schema = new Schema( + { + name: { + type: String, + required: true, + trim: true, + unique: true, + uppercase: true, + validate: { + validator: (value: string) => value.length > 0, + }, + }, + authorities: { + type: [String], + required: true, + default: [], + validate: { + validator: (value: string[]) => + value.every((v) => + validator.isIn(v, Object.values(Actions)) + ), + }, + }, + restrictions: { + type: [String], + required: true, + default: [], + validate: { + validator: (value: string[]) => + value.every((v) => + validator.isIn(v, Object.values(Actions)) + ), + }, + }, + }, + { + timestamps: true, + } +); + +const roleModel = mongoose.model('Role', roleSchema); +export default roleModel; diff --git a/backend-app/models/user/user_model.js b/backend-app/models/user/user_model.ts similarity index 60% rename from backend-app/models/user/user_model.js rename to backend-app/models/user/user_model.ts index 3792e8d..519f3b4 100644 --- a/backend-app/models/user/user_model.js +++ b/backend-app/models/user/user_model.ts @@ -1,10 +1,12 @@ -const mongoose = require('mongoose'); -const validator = require('validator'); -const bcrypt = require('bcrypt'); -const Actions = require('../../constants/actions'); -const metaData = require('../../constants/meta_data'); +import mongoose, { Model, Schema } from 'mongoose'; +import validator from 'validator'; +import bcrypt from 'bcrypt'; +import Actions from '@constants/actions'; +import metaData from '@constants/meta_data'; +import { randomBytes, createHash } from 'crypto'; +import { IUser } from '@interfaces/models/i_user'; -const userSchema = new mongoose.Schema( +const userSchema: Schema = new mongoose.Schema( { name: { type: String, @@ -22,15 +24,14 @@ const userSchema = new mongoose.Schema( }, password: { type: String, - allowNull: true, minLength: 6, select: false, }, authorities: { - type: Array, + type: [String], default: [], validate: { - validator: function (el) { + validator: function (el: string[]) { return el.every((action) => Object.values(Actions).includes(action) ); @@ -39,10 +40,10 @@ const userSchema = new mongoose.Schema( message: 'Please provide a valid action', }, restrictions: { - type: Array, + type: [String], default: [], validate: { - validator: function (el) { + validator: function (el: string[]) { return el.every((action) => Object.values(Actions).includes(action) ); @@ -51,7 +52,7 @@ const userSchema = new mongoose.Schema( }, }, roles: { - type: Array, + type: [String], default: [], }, active: { @@ -71,6 +72,10 @@ const userSchema = new mongoose.Schema( select: false, default: null, }, + resetKey: { + type: String, + select: false, + }, }, { timestamps: true } ); @@ -78,7 +83,7 @@ const userSchema = new mongoose.Schema( // add meta data to the schema metaData.apply(userSchema); -userSchema.pre('save', async function (next) { +userSchema.pre('save', async function (next) { if ( !this.isModified('password') || this.password === undefined || @@ -90,19 +95,28 @@ userSchema.pre('save', async function (next) { next(); }); -userSchema.methods.correctPassword = function ( - typedPassword, - originalPassword +userSchema.methods.correctPassword = async function ( + typedPassword: string, + originalPassword: string ) { - return bcrypt.compare(typedPassword, originalPassword); + const isTrue = await bcrypt.compare(typedPassword, originalPassword); + return isTrue; }; // verify if the user is authorized or restricted from an action -userSchema.methods.isAuthorizedTo = function (action) { - return this.authorities.includes(action); +userSchema.methods.isAuthorizedTo = function (actions: string[]) { + return actions.every((action) => this.authorities.includes(action)); }; -userSchema.methods.isRestrictedFrom = function (action) { - return this.restrictions.includes(action); + +userSchema.methods.isRestrictedFrom = function (actions: string[]) { + return actions.some((action) => this.restrictions.includes(action)); +}; + +// generateResetKey +userSchema.methods.generateResetKey = function () { + const resetKey = randomBytes(32).toString('hex'); + this.resetKey = createHash('sha256').update(resetKey).digest('hex'); + return resetKey; }; userSchema.index( @@ -118,5 +132,5 @@ userSchema.pre('findOne', function () { this.where({ deleted: false }); }); -const User = mongoose.model('User', userSchema); -module.exports = User; +const User: Model = mongoose.model('User', userSchema); +export default User; diff --git a/backend-app/nodemon.json b/backend-app/nodemon.json new file mode 100644 index 0000000..766c392 --- /dev/null +++ b/backend-app/nodemon.json @@ -0,0 +1,4 @@ +{ + "exec": "ts-node-dev server.ts", + "watch": ["."] +} diff --git a/backend-app/package-lock.json b/backend-app/package-lock.json index f8ba93d..d965e88 100644 --- a/backend-app/package-lock.json +++ b/backend-app/package-lock.json @@ -9,53 +9,66 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@typescript-eslint/parser": "6.5.0", + "@inquirer/prompts": "3.1.1", + "@typegoose/typegoose": "11.5.0", + "@types/bcrypt": "5.0.0", + "@types/chai": "4.3.6", + "@types/compression": "1.7.3", + "@types/cookie-parser": "1.4.4", + "@types/cors": "2.8.14", + "@types/expect": "24.3.0", + "@types/express": "4.17.17", + "@types/express-routes-versioning": "1.0.1", + "@types/hpp": "0.2.3", + "@types/jsonwebtoken": "9.0.3", + "@types/mocha": "10.0.2", + "@types/morgan": "1.9.5", + "@types/node": "^16.11.7", + "@types/supertest": "2.0.13", + "@types/swagger-jsdoc": "6.0.1", + "@types/swagger-ui-express": "4.1.3", + "@types/validator": "13.11.1", + "@typescript-eslint/parser": "6.7.2", "axios": "1.5.0", "bcrypt": "5.1.1", + "chai": "4.3.10", "compression": "1.7.4", "cookie-parser": "^1.4.5", "cors": "^2.8.5", "dotenv": "16.3.1", - "express": "^4.17.1", + "eslint": "8.48.0", + "eslint-config-prettier": "9.0.0", + "eslint-plugin-prettier": "5.0.0", + "express": "4.18.2", "express-bearer-token": "2.4.0", "express-mongo-sanitize": "2.2.0", "express-rate-limit": "6.10.0", "express-routes-versioning": "1.0.1", + "express-swagger-generator": "1.1.17", "helmet": "4.6.0", "hpp": "0.2.3", "http-status-codes": "2.2.0", + "husky": "7.0.4", "jsonwebtoken": "9.0.2", + "lint-staged": "14.0.1", + "mocha": "10.2.0", "mongoose": "7.5.0", "morgan": "1.10.0", + "prettier": "3.0.3", "qs": "6.11.2", "supertest": "6.3.3", - "swagger-autogen": "2.23.5", + "swagger-jsdoc": "6.2.8", "swagger-ui-express": "5.0.0", + "ts-mocha": "10.0.0", + "ts-node": "^10.4.0", "ts-node-dev": "2.0.0", - "validator": "^13.11.0", + "tsconfig-paths": "4.2.0", + "tsoa": "5.1.1", + "typescript": "5.2.2", + "validator": "13.11.0", "winston": "^3.10.0", "winston-daily-rotate-file": "^4.7.1", - "xss-clean": "^0.1.4", - "yamljs": "^0.3.0" - }, - "devDependencies": { - "@types/body-parser": "^1.19.0", - "@types/cookie-parser": "^1.4.2", - "@types/cors": "^2.8.10", - "@types/express": "^4.17.13", - "@types/helmet": "^4.0.0", - "@types/node": "^16.11.7", - "eslint": "8.48.0", - "eslint-config-prettier": "9.0.0", - "eslint-plugin-prettier": "5.0.0", - "husky": "7.0.4", - "jest": "27.5.1", - "lint-staged": "14.0.1", - "prettier": "3.0.3", - "ts-jest": "^27.1.3", - "ts-node": "^10.4.0", - "tsconfig-paths": "4.2.0", - "typescript": "^4.4.4" + "xss-clean": "^0.1.4" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -66,339 +79,159 @@ "node": ">=0.10.0" } }, - "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", + "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" } }, - "node_modules/@babel/code-frame/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==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } + "node_modules/@apidevtools/json-schema-ref-parser/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, - "node_modules/@babel/code-frame/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==", - "dev": true, + "node_modules/@apidevtools/json-schema-ref-parser/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "argparse": "^2.0.1" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/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": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@babel/compat-data": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", - "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", - "dev": true, + "node_modules/@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", "engines": { - "node": ">=6.9.0" + "node": ">=10" } }, - "node_modules/@babel/core": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.11.tgz", - "integrity": "sha512-lh7RJrtPdhibbxndr6/xx0w8+CVlY5FJZiaSz908Fpy+G0xkBFTvwLcKJFF4PJxVfGhVWNebikpWGnOoC71juQ==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.10", - "@babel/generator": "^7.22.10", - "@babel/helper-compilation-targets": "^7.22.10", - "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.11", - "@babel/parser": "^7.22.11", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.11", - "@babel/types": "^7.22.11", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==" }, - "node_modules/@babel/core/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, + "node_modules/@apidevtools/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", "dependencies": { - "ms": "2.1.2" + "@apidevtools/json-schema-ref-parser": "^9.0.6", + "@apidevtools/openapi-schemas": "^2.0.4", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "call-me-maybe": "^1.0.1", + "z-schema": "^5.0.1" }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/core/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "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==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "peerDependencies": { + "openapi-types": ">=7" } }, - "node_modules/@babel/generator": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", - "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.10", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, + "node_modules/@apidevtools/swagger-parser/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "optional": true, "engines": { - "node": ">=6.9.0" + "node": "^12.20.0 || >=14" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", - "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", - "dev": true, + "node_modules/@apidevtools/swagger-parser/node_modules/z-schema": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", + "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.5", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/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==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "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==", - "dev": true, "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "z-schema": "bin/z-schema" }, "engines": { - "node": ">=6.9.0" + "node": ">=8.0.0" + }, + "optionalDependencies": { + "commander": "^9.4.1" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", - "dev": true, + "node_modules/@babel/code-frame/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==", "dependencies": { - "@babel/types": "^7.22.5" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=4" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", - "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", - "dev": true, + "node_modules/@babel/code-frame/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": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true, "engines": { - "node": ">=6.9.0" + "node": ">=4" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { - "node": ">=6.9.0" + "node": ">=4" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, + "node_modules/@babel/code-frame/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": { - "@babel/types": "^7.22.5" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true, - "engines": { - "node": ">=6.9.0" + "node": ">=4" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.11.tgz", - "integrity": "sha512-vyOXC8PBWaGc5h7GMsNx68OH33cypkEDJCHvYVVgVbbxJDROYVtexSk0gK5iCF1xNjRIN2s8ai7hwkWDq5szWg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.11", - "@babel/types": "^7.22.11" - }, + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz", - "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==", - "dev": true, + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, @@ -410,7 +243,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -422,7 +254,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -432,325 +263,83 @@ "node": ">=4" } }, - "node_modules/@babel/highlight/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": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { - "node": ">=0.8.0" + "node": ">=4" } }, - "node_modules/@babel/parser": { - "version": "7.22.14", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.14.tgz", - "integrity": "sha512-1KucTHgOvaw/LzCVrEOAyXkr9rQlp0A1HiHRYnSUE9dmb8PvPW7o5sscg+5169r54n3vGlbx6GevTE/Iw/P3AQ==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" + "node_modules/@babel/highlight/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": ">=6.0.0" + "node": ">=4" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "engines": { + "node": ">=0.1.90" } }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@jridgewell/trace-mapping": "0.3.9" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=12" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" } }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "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", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "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", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.11.tgz", - "integrity": "sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.10", - "@babel/generator": "^7.22.10", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.11", - "@babel/types": "^7.22.11", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/traverse/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@babel/types": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz", - "integrity": "sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", - "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", - "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", - "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node_modules/@eslint-community/regexpp": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", + "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { @@ -896,283 +485,220 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, + "node_modules/@inquirer/checkbox": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-1.3.11.tgz", + "integrity": "sha512-SaQBDr7niZQzoP5Mqzak5pQY7476mvf4Sj2V8VFrbFHWHsavy3nKGKEOgijNHy151bEgqDog1829g/pKa9Qcrw==", "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" + "@inquirer/core": "^5.0.0", + "@inquirer/type": "^1.1.4", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "figures": "^3.2.0" }, "engines": { - "node": ">=8" + "node": ">=14.18.0" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, + "node_modules/@inquirer/confirm": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-2.0.12.tgz", + "integrity": "sha512-Oxz3L0ti+0nWYHPPUIrPkxA2KnQZUGBHnk56yF5RjKqPGFrwvgLZdIXNe/w4I/OtdLeOBqHCrJ+kCvNvHVdk9g==", + "dependencies": { + "@inquirer/core": "^5.0.0", + "@inquirer/type": "^1.1.4", + "chalk": "^4.1.2" + }, "engines": { - "node": ">=8" + "node": ">=14.18.0" } }, - "node_modules/@jest/console": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", - "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0" + "node_modules/@inquirer/core": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-5.0.0.tgz", + "integrity": "sha512-q2o4BcANKFyuUI5V6ejmPs1f9SdbJxfnLmhQVb72Fj7hOudoKsJpByJZ0imv9a/rpKDogA+93vtBBMqsnS7/Fg==", + "dependencies": { + "@inquirer/type": "^1.1.4", + "@types/mute-stream": "^0.0.1", + "@types/node": "^20.6.0", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "cli-spinners": "^2.9.0", + "cli-width": "^4.1.0", + "figures": "^3.2.0", + "mute-stream": "^1.0.0", + "run-async": "^3.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=14.18.0" } }, - "node_modules/@jest/core": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", - "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", - "dev": true, - "dependencies": { - "@jest/console": "^27.5.1", - "@jest/reporters": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^27.5.1", - "jest-config": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-resolve-dependencies": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "jest-watcher": "^27.5.1", - "micromatch": "^4.0.4", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, + "node_modules/@inquirer/core/node_modules/@types/node": { + "version": "20.6.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.3.tgz", + "integrity": "sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA==" + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": ">=14" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@jest/environment": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", - "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", - "dev": true, + "node_modules/@inquirer/editor": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-1.2.10.tgz", + "integrity": "sha512-aluYpazbxIdM54L+xNmVHzOjoXGwkliTCvHxhtPg6itmqDGMVmU1z+T2akHt6Xnx9RyrTpbumFB4xn1iI0UfnA==", "dependencies": { - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1" + "@inquirer/core": "^5.0.0", + "@inquirer/type": "^1.1.4", + "chalk": "^4.1.2", + "external-editor": "^3.1.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=14.18.0" } }, - "node_modules/@jest/fake-timers": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", - "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", - "dev": true, + "node_modules/@inquirer/expand": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-1.1.11.tgz", + "integrity": "sha512-GSZJbYKPBniyXgWeFLsqiv7TSK9QjpQqCr+i/85Yts3wwixXTrAeoqM3TVVgHO/3j+xeFcuhOm1wy/F2QY5aEg==", "dependencies": { - "@jest/types": "^27.5.1", - "@sinonjs/fake-timers": "^8.0.1", - "@types/node": "*", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" + "@inquirer/core": "^5.0.0", + "@inquirer/type": "^1.1.4", + "chalk": "^4.1.2", + "figures": "^3.2.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=14.18.0" } }, - "node_modules/@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", - "dev": true, + "node_modules/@inquirer/input": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-1.2.11.tgz", + "integrity": "sha512-sV1nO6+RxMFTHAznmxMkbMkjGQ8NGMWr0mvXjU35YQ0OFEL+YlD+DPbNd9s3ltnswODZAcnM1yFvdko3S/Kj/w==", "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" + "@inquirer/core": "^5.0.0", + "@inquirer/type": "^1.1.4", + "chalk": "^4.1.2" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=14.18.0" } }, - "node_modules/@jest/reporters": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", - "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", - "dev": true, + "node_modules/@inquirer/password": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-1.1.11.tgz", + "integrity": "sha512-r2eiLMlTuY+k+yJf6XLbnAEz7EDyWdjOrgVAWjSKoEDBc3T9/rq2I+7WiY9FUFArYY/1LxmsNWavs5NuMICx8Q==", "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.2", - "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-haste-map": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "slash": "^3.0.0", - "source-map": "^0.6.0", - "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.1.0" + "@inquirer/input": "^1.2.11", + "@inquirer/type": "^1.1.4", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/prompts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-3.1.1.tgz", + "integrity": "sha512-7m/7Q4eupJYmn0GxM1H1dcekE4F4YlIB6bSKZs2SVeShARYUVPiAKFZ9c15UzYnBtdjCv4zXI17jbNtCNqmxGQ==", + "dependencies": { + "@inquirer/checkbox": "^1.3.11", + "@inquirer/confirm": "^2.0.12", + "@inquirer/core": "^5.0.0", + "@inquirer/editor": "^1.2.10", + "@inquirer/expand": "^1.1.11", + "@inquirer/input": "^1.2.11", + "@inquirer/password": "^1.1.11", + "@inquirer/rawlist": "^1.2.11", + "@inquirer/select": "^1.2.11" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "engines": { + "node": ">=14.18.0" } }, - "node_modules/@jest/source-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", - "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", - "dev": true, + "node_modules/@inquirer/rawlist": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-1.2.11.tgz", + "integrity": "sha512-4S2t2pCCR3VgyB3lbPKoiJ9020HHAi9g4M+DIyXHYwGE++7wURAwKkzb6v78fS0yKfCbyFt3BTcL2UffQRQ9Fg==", "dependencies": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9", - "source-map": "^0.6.0" + "@inquirer/core": "^5.0.0", + "@inquirer/type": "^1.1.4", + "chalk": "^4.1.2" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=14.18.0" } }, - "node_modules/@jest/test-result": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", - "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", - "dev": true, + "node_modules/@inquirer/select": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-1.2.11.tgz", + "integrity": "sha512-LH2wzAsWfu/+wcapeht07zTDefuvGTpv0+9dCAQ68QigF+4gHzpWq5+AbBLbxzuH2Wz4WlHcti85nFUPPM1t3A==", "dependencies": { - "@jest/console": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "@inquirer/core": "^5.0.0", + "@inquirer/type": "^1.1.4", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "figures": "^3.2.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/type": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.1.4.tgz", + "integrity": "sha512-a6+RCiXBQEbiA73RT1pBfwiH2I+MPcoZoGKuuUYFkws+6ud7nb5kUQGHFGUSBim25IyVMT/mqbWIrkxetcIb/w==", + "engines": { + "node": ">=14.18.0" } }, - "node_modules/@jest/test-sequencer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", - "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", - "dev": true, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dependencies": { - "@jest/test-result": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-runtime": "^27.5.1" + "jest-get-type": "^29.6.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/transform": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", - "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", - "dev": true, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dependencies": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.5.1", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-util": "^27.5.1", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", - "dev": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dependencies": { + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "@types/yargs": "^16.0.0", + "@types/yargs": "^17.0.8", "chalk": "^4.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -1183,29 +709,15 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" }, "node_modules/@mapbox/node-pre-gyp": { "version": "1.0.11", @@ -1248,20 +760,6 @@ "semver": "bin/semver.js" } }, - "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@mongodb-js/saslprep": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", @@ -1307,7 +805,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "fast-glob": "^3.3.0", @@ -1323,32 +820,10 @@ "url": "https://opencollective.com/unts" } }, - "node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", - "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" }, "node_modules/@tsconfig/node10": { "version": "1.0.9", @@ -1370,89 +845,239 @@ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" }, - "node_modules/@types/babel__core": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", - "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", - "dev": true, + "node_modules/@tsoa/cli": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@tsoa/cli/-/cli-5.1.1.tgz", + "integrity": "sha512-krvp6Qr2yPUfj6bJRs0vwQhLANeINzyusNnzgSoerDfBBBnjZ+VhvR4rWguAcLc1kgP/kFAJz5kIp4iqLFmILQ==", "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "@tsoa/runtime": "^5.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.1.0", + "glob": "^8.0.3", + "handlebars": "^4.7.7", + "merge": "^2.1.1", + "minimatch": "^5.1.0", + "typescript": "^4.9.5", + "validator": "^13.7.0", + "yamljs": "^0.3.0", + "yargs": "^17.5.1" + }, + "bin": { + "tsoa": "dist/cli.js" + }, + "engines": { + "node": ">=12.0.0", + "yarn": ">=1.9.4" } }, - "node_modules/@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, + "node_modules/@tsoa/cli/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dependencies": { - "@babel/types": "^7.0.0" + "balanced-match": "^1.0.0" } }, - "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, + "node_modules/@tsoa/cli/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@tsoa/cli/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@tsoa/cli/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tsoa/cli/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/@tsoa/cli/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@tsoa/cli/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@tsoa/cli/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@tsoa/runtime": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@tsoa/runtime/-/runtime-5.0.0.tgz", + "integrity": "sha512-DY0x7ZhNRF9FcwCZXQQbQhVj3bfZe0LScNyqp0c8PhDTj0gRMjY4ESVpihopRzhQtamReJoDRg3FhEu4BlSVtA==", "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "@types/multer": "^1.4.7", + "promise.any": "^2.0.5", + "reflect-metadata": "^0.1.13", + "validator": "^13.7.0" + }, + "engines": { + "node": ">=12.0.0", + "yarn": ">=1.9.4" + } + }, + "node_modules/@typegoose/typegoose": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/@typegoose/typegoose/-/typegoose-11.5.0.tgz", + "integrity": "sha512-+ca//+8hUzOdK7mJTxHwqMiQjarVGCkF5x073ZScXfWOw35kPOzvvQwBEqFiVMhKW5txkiswsALwriJxhYcO2A==", + "dependencies": { + "lodash": "^4.17.20", + "loglevel": "^1.8.1", + "reflect-metadata": "^0.1.13", + "semver": "^7.5.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.17.0" + }, + "peerDependencies": { + "mongoose": "~7.5.0" } }, - "node_modules/@types/babel__traverse": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", - "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", - "dev": true, + "node_modules/@types/bcrypt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz", + "integrity": "sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw==", "dependencies": { - "@babel/types": "^7.20.7" + "@types/node": "*" } }, "node_modules/@types/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, "dependencies": { "@types/connect": "*", "@types/node": "*" } }, + "node_modules/@types/chai": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.6.tgz", + "integrity": "sha512-VOVRLM1mBxIRxydiViqPcKn6MIxZytrbMpd6RJLIWKxUNr3zux8no0Oc7kJx0WAPIitgZ0gkrDS+btlqQpubpw==" + }, + "node_modules/@types/compression": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.3.tgz", + "integrity": "sha512-rKquEGjebqizyHNMOpaE/4FdYR5VQiWFeesqYfvJU0seSEyB4625UGhNOO/qIkH10S3wftiV7oefc8WdLZ/gCQ==", + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/cookie-parser": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.3.tgz", - "integrity": "sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==", - "dev": true, + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.4.tgz", + "integrity": "sha512-Var+aj5I6ZgIqsQ05N2V8q5OBrFfZXtIGWWDSrEYLIbMw758obagSwdGcLCjwh1Ga7M7+wj0SDIAaAC/WT7aaA==", "dependencies": { "@types/express": "*" } }, + "node_modules/@types/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==" + }, "node_modules/@types/cors": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", - "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", - "dev": true, + "version": "2.8.14", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.14.tgz", + "integrity": "sha512-RXHUvNWYICtbP6s18PnOCaqToK8y14DnLd75c6HfyKf228dxy7pHNOQkxPtvXKp/hINFMDjbYzsj63nnpPMSRQ==", "dependencies": { "@types/node": "*" } }, + "node_modules/@types/expect": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/@types/expect/-/expect-24.3.0.tgz", + "integrity": "sha512-aq5Z+YFBz5o2b6Sp1jigx5nsmoZMK5Ceurjwy6PZmRv7dEi1jLtkARfvB1ME+OXJUG+7TZUDcv3WoCr/aor6dQ==", + "deprecated": "This is a stub types definition. expect provides its own type definitions, so you do not need this installed.", + "dependencies": { + "expect": "*" + } + }, "node_modules/@types/express": { "version": "4.17.17", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", - "dev": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -1460,11 +1085,18 @@ "@types/serve-static": "*" } }, + "node_modules/@types/express-routes-versioning": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/express-routes-versioning/-/express-routes-versioning-1.0.1.tgz", + "integrity": "sha512-IeLqOK/z1ABX8xBr+7vTltWTfj1eHqDfj5b2+59cJ1J4Tp6sHEF27lVw/3KtHRYqn+Yv1OWpdfHEm2YJGAQ7sw==", + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/express-serve-static-core": { "version": "4.17.36", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz", "integrity": "sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q==", - "dev": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -1472,42 +1104,28 @@ "@types/send": "*" } }, - "node_modules/@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/helmet": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/helmet/-/helmet-4.0.0.tgz", - "integrity": "sha512-ONIn/nSNQA57yRge3oaMQESef/6QhoeX7llWeDli0UZIfz8TQMkfNPTXA8VnnyeA1WUjG2pGqdjEIueYonMdfQ==", - "deprecated": "This is a stub types definition. helmet provides its own type definitions, so you do not need this installed.", - "dev": true, + "node_modules/@types/hpp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@types/hpp/-/hpp-0.2.3.tgz", + "integrity": "sha512-EIbnUHlMgZ7lndrm6p8GZsFnnFnw1w17ZWwT5q/6Mb+62o8BqdpgKxvEZFTYVOqOsOhXEbFmWSzZXVurP0XSnQ==", "dependencies": { - "helmet": "*" + "@types/express": "*" } }, "node_modules/@types/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==", - "dev": true + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } @@ -1516,45 +1134,82 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", + "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "optional": true + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-b0jGiOgHtZ2jqdPgPnP6WLCXZk1T8p06A/vPGzUvxpFGgKMbjXJDjC5m52ErqBnIuWZFgGoIJyRdeG5AyreJjA==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "node_modules/@types/mocha": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.2.tgz", + "integrity": "sha512-NaHL0+0lLNhX6d9rs+NSt97WH/gIlRHmszXbQ/8/MV/eVcFNdeJ/GYhrFuUc8K7WuPhRhTSdMkCp8VMzhUq85w==" + }, + "node_modules/@types/morgan": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.5.tgz", + "integrity": "sha512-5TgfIWm0lcTGnbCZExwc19dCOMOMmAiiBZQj8Ko3NRxsVDgRxf+AEGRQTqNVA5Yh2xfdWp4clbAEMbYP+jkOqg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/multer": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.8.tgz", + "integrity": "sha512-VMZOW6mnmMMhA5m3fsCdXBwFwC+a+27/8gctNMuQC4f7UtWcF79KAFGoIfKZ4iqrElgWIa3j5vhMJDp0iikQ1g==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/mute-stream": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.1.tgz", + "integrity": "sha512-0yQLzYhCqGz7CQPE3iDmYjhb7KMBFOP+tBkyw+/Y2YyDI5wpS7itXXxneN1zSsUwWx3Ji6YiVYrhAnpQGS/vkw==", + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/node": { "version": "16.18.47", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.47.tgz", "integrity": "sha512-yBaT6qZKmvaeTuv8kfv2QwIsgi/D4bYSLmHow/IBxjLNRHxYEXgwVRvBmnNLBXi3CkZg0Wdzu3NTUlUjjxconQ==" }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true - }, "node_modules/@types/qs": { "version": "6.9.8", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", - "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", - "dev": true + "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==" }, "node_modules/@types/range-parser": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, "node_modules/@types/send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", - "dev": true, "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -1564,7 +1219,6 @@ "version": "1.15.2", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", - "dev": true, "dependencies": { "@types/http-errors": "*", "@types/mime": "*", @@ -1574,8 +1228,7 @@ "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" }, "node_modules/@types/strip-bom": { "version": "3.0.0", @@ -1587,11 +1240,47 @@ "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==" }, + "node_modules/@types/superagent": { + "version": "4.1.19", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.19.tgz", + "integrity": "sha512-McM1mlc7PBZpCaw0fw/36uFqo0YeA6m8JqoyE4OfqXsZCIg0hPP2xdE6FM7r6fdprDZHlJwDpydUj1R++93hCA==", + "dependencies": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "node_modules/@types/supertest": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.13.tgz", + "integrity": "sha512-Vc/5/pRwSC055fU7Wu8erTj4gLpID9SdG2zRMuqaHLni3GTsrJ8gyB6MbFZZGLW6vQaGPhiUWRB6uWglv87MEg==", + "dependencies": { + "@types/superagent": "*" + } + }, + "node_modules/@types/swagger-jsdoc": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.1.tgz", + "integrity": "sha512-+MUpcbyxD528dECUBCEVm6abNuORdbuGjbrUdHDeAQ+rkPuo2a+L4N02WJHF3bonSSE6SJ3dUJwF2V6+cHnf0w==" + }, + "node_modules/@types/swagger-ui-express": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.3.tgz", + "integrity": "sha512-jqCjGU/tGEaqIplPy3WyQg+Nrp6y80DCFnDEAvVKWkJyv0VivSSDCChkppHRHAablvInZe6pijDFMnavtN0vqA==", + "dependencies": { + "@types/express": "*", + "@types/serve-static": "*" + } + }, "node_modules/@types/triple-beam": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.2.tgz", "integrity": "sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g==" }, + "node_modules/@types/validator": { + "version": "13.11.1", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.1.tgz", + "integrity": "sha512-d/MUkJYdOeKycmm75Arql4M5+UuXmf4cHdHKsyw1GcvnNgL6s77UkgSgJ8TE/rI5PYsnwYq5jkcWBLuN/MpQ1A==" + }, "node_modules/@types/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -1606,11 +1295,15 @@ "@types/webidl-conversions": "*" } }, + "node_modules/@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==" + }, "node_modules/@types/yargs": { - "version": "16.0.5", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", - "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", - "dev": true, + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dependencies": { "@types/yargs-parser": "*" } @@ -1618,18 +1311,17 @@ "node_modules/@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, "node_modules/@typescript-eslint/parser": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.5.0.tgz", - "integrity": "sha512-LMAVtR5GN8nY0G0BadkG0XIe4AcNMeyEy3DyhKGAh9k4pLSMBO7rF29JvDBpZGCmp5Pgz5RLHP6eCpSYZJQDuQ==", - "dependencies": { - "@typescript-eslint/scope-manager": "6.5.0", - "@typescript-eslint/types": "6.5.0", - "@typescript-eslint/typescript-estree": "6.5.0", - "@typescript-eslint/visitor-keys": "6.5.0", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.2.tgz", + "integrity": "sha512-KA3E4ox0ws+SPyxQf9iSI25R6b4Ne78ORhNHeVKrPQnoYsb9UhieoiRoJgrzgEeKGOXhcY1i8YtOeCHHTDa6Fw==", + "dependencies": { + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4" }, "engines": { @@ -1670,12 +1362,12 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.5.0.tgz", - "integrity": "sha512-A8hZ7OlxURricpycp5kdPTH3XnjG85UpJS6Fn4VzeoH4T388gQJ/PGP4ole5NfKt4WDVhmLaQ/dBLNDC4Xl/Kw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", + "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", "dependencies": { - "@typescript-eslint/types": "6.5.0", - "@typescript-eslint/visitor-keys": "6.5.0" + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1686,9 +1378,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.5.0.tgz", - "integrity": "sha512-eqLLOEF5/lU8jW3Bw+8auf4lZSbbljHR2saKnYqON12G/WsJrGeeDHWuQePoEf9ro22+JkbPfWQwKEC5WwLQ3w==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", + "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -1698,12 +1390,12 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.5.0.tgz", - "integrity": "sha512-q0rGwSe9e5Kk/XzliB9h2LBc9tmXX25G0833r7kffbl5437FPWb2tbpIV9wAATebC/018pGa9fwPDuvGN+LxWQ==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", + "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", "dependencies": { - "@typescript-eslint/types": "6.5.0", - "@typescript-eslint/visitor-keys": "6.5.0", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1745,11 +1437,11 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.5.0.tgz", - "integrity": "sha512-yCB/2wkbv3hPsh02ZS8dFQnij9VVQXJMN/gbQsaaY+zxALkZnxa/wagvLEFsAWMPv7d7lxQmNsIzGU1w/T/WyA==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", + "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", "dependencies": { - "@typescript-eslint/types": "6.5.0", + "@typescript-eslint/types": "6.7.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1760,12 +1452,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -1787,6 +1473,7 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1794,16 +1481,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - } - }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -1812,15 +1489,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -1868,11 +1536,18 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, "dependencies": { "type-fest": "^0.21.3" }, @@ -1963,6 +1638,18 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -1976,11 +1663,65 @@ "node": ">=8" } }, + "node_modules/array.prototype.map": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.6.tgz", + "integrity": "sha512-nK1psgF2cXqP3wSyCSq0Hc7zwNq3sfljQqaG27r/7a7ooNUnn5nGq6yYWyks9jMO5EoFQ0ax80hSg6oXSRNXaw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "engines": { + "node": "*" + } + }, "node_modules/async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", @@ -1991,6 +1732,17 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/axios": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz", @@ -2001,98 +1753,6 @@ "proxy-from-env": "^1.1.0" } }, - "node_modules/babel-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", - "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", - "dev": true, - "dependencies": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", - "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@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-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", - "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", - "dev": true, - "dependencies": { - "babel-plugin-jest-hoist": "^27.5.1", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2131,7 +1791,6 @@ "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true, "engines": { "node": ">=0.6" } @@ -2185,7 +1844,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, "dependencies": { "big-integer": "^1.6.44" }, @@ -2213,64 +1871,10 @@ "node": ">=8" } }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.21.10", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", - "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001517", - "electron-to-chromium": "^1.4.477", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.11" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "dependencies": { - "node-int64": "^0.4.0" - } + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" }, "node_modules/bson": { "version": "5.4.0", @@ -2294,7 +1898,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dev": true, "dependencies": { "run-applescript": "^5.0.0" }, @@ -2325,6 +1928,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2334,33 +1942,32 @@ } }, "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001525", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001525.tgz", - "integrity": "sha512-/3z+wB4icFt3r0USMwxujAqRvaD/B7rvGTsKhbhSQErVrJvkZCLhgNLJxU8MevahQVH6hCU9FsHdNUFbiwmE7Q==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] + "node_modules/chai": { + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", + "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } }, "node_modules/chalk": { "version": "4.1.2", @@ -2377,14 +1984,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chalk/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/chalk/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -2396,13 +1995,20 @@ "node": ">=8" } }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dependencies": { + "get-func-name": "^2.0.2" + }, "engines": { - "node": ">=10" + "node": "*" } }, "node_modules/chokidar": { @@ -2443,7 +2049,6 @@ "version": "3.8.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true, "funding": [ { "type": "github", @@ -2454,17 +2059,10 @@ "node": ">=8" } }, - "node_modules/cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true - }, "node_modules/cli-cursor": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "dev": true, "dependencies": { "restore-cursor": "^4.0.0" }, @@ -2475,11 +2073,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-spinners": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", + "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-truncate": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dev": true, "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^5.0.0" @@ -2495,7 +2103,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "engines": { "node": ">=12" }, @@ -2506,14 +2113,12 @@ "node_modules/cli-truncate/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/cli-truncate/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -2530,7 +2135,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -2541,33 +2145,40 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "engines": { + "node": ">= 12" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true - }, "node_modules/color": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", @@ -2610,8 +2221,7 @@ "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" }, "node_modules/colorspace": { "version": "1.1.4", @@ -2637,7 +2247,6 @@ "version": "11.0.0", "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", - "dev": true, "engines": { "node": ">=16" } @@ -2717,12 +2326,6 @@ "node": ">= 0.6" } }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, "node_modules/cookie": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", @@ -2761,6 +2364,13 @@ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==" }, + "node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "hasInstallScript": true + }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -2791,99 +2401,36 @@ "node": ">= 8" } }, - "node_modules/cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" + "ms": "2.0.0" } }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "node_modules/data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "engines": { "node": ">=10" - } - }, - "node_modules/data-urls/node_modules/tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "dependencies": { - "punycode": "^2.1.1" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/data-urls/node_modules/webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true, - "engines": { - "node": ">=10.4" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/data-urls/node_modules/whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" + "type-detect": "^4.0.0" }, "engines": { - "node": ">=10" - } - }, - "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" + "node": ">=6" } }, - "node_modules/decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true - }, - "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -2901,7 +2448,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", - "dev": true, "dependencies": { "bundle-name": "^3.0.0", "default-browser-id": "^3.0.0", @@ -2919,7 +2465,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dev": true, "dependencies": { "bplist-parser": "^0.2.0", "untildify": "^4.0.0" @@ -2935,7 +2480,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.1", @@ -2958,7 +2502,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, "engines": { "node": ">=14.18.0" } @@ -2967,7 +2510,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -2979,7 +2521,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, "engines": { "node": ">=12" }, @@ -2991,7 +2532,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, "dependencies": { "path-key": "^4.0.0" }, @@ -3006,7 +2546,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, "dependencies": { "mimic-fn": "^4.0.0" }, @@ -3021,7 +2560,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -3033,7 +2571,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, "engines": { "node": ">=12" }, @@ -3041,11 +2578,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/define-data-property": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz", + "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/define-lazy-prop": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, "engines": { "node": ">=12" }, @@ -3053,6 +2602,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3091,15 +2656,6 @@ "node": ">=8" } }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/dezalgo": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", @@ -3118,12 +2674,11 @@ } }, "node_modules/diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "dev": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/dir-glob": { @@ -3148,25 +2703,23 @@ "node": ">=6.0.0" } }, - "node_modules/domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, + "node_modules/doctrine-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/doctrine-file/-/doctrine-file-1.0.3.tgz", + "integrity": "sha512-OK37HbZtNmIMn84riibVXRmcEGUIf6BNfYMcbXg20ejP+LEsf4tnk8QfYy3EmQs4KzZFhTl3zwoKqVwARxpBgA==", "dependencies": { - "webidl-conversions": "^5.0.0" - }, - "engines": { - "node": ">=8" + "doctrine": "^2.0.0" } }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true, + "node_modules/doctrine-file/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" + }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/dotenv": { @@ -3191,8 +2744,7 @@ "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", @@ -3207,24 +2759,6 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, - "node_modules/electron-to-chromium": { - "version": "1.4.508", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.508.tgz", - "integrity": "sha512-FFa8QKjQK/A5QuFr2167myhMesGrhlOBD+3cYNxO9/S4XzHEXesyTD/1/xF644gC8buFPz3ca6G1LOQD0tZrrg==", - "dev": true - }, - "node_modules/emittery": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3243,26 +2777,136 @@ "node": ">= 0.8" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, + "node_modules/es-abstract": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz", + "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.1", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-aggregate-error": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.11.tgz", + "integrity": "sha512-DCiZiNlMlbvofET/cE55My387NiLvuGToBEZDdK9U2G3svDCjL8WOgO5Il6lO83nQ8qmag/R9nArdpaFQ/m3lA==", + "dependencies": { + "define-data-property": "^1.1.0", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", "dependencies": { - "is-arrayish": "^0.2.1" + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/error-ex/node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, "engines": { "node": ">=6" } @@ -3273,33 +2917,11 @@ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" + "node": ">=0.8.0" } }, "node_modules/eslint": { @@ -3359,7 +2981,6 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", - "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -3371,7 +2992,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz", "integrity": "sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==", - "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.8.5" @@ -3454,21 +3074,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -3505,43 +3110,15 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "engines": { "node": ">=10" }, @@ -3580,7 +3157,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -3638,14 +3214,12 @@ "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -3664,28 +3238,19 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/expect": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", - "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dependencies": { - "@jest/types": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/express": { @@ -3773,6 +3338,38 @@ "resolved": "https://registry.npmjs.org/express-routes-versioning/-/express-routes-versioning-1.0.1.tgz", "integrity": "sha512-lzTLVyGFdyaahAN2rfBvnPJKsSMy0fAfMMmkRif1MLXZCNvp1BwRepnhVh0WEn8z39AXPdCeIzibds7qidbAow==" }, + "node_modules/express-swagger-generator": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/express-swagger-generator/-/express-swagger-generator-1.1.17.tgz", + "integrity": "sha512-eKB2cR3TcvmSepkqjm9sFPqPAV7PQawyc3Df2p9/0vN4Q7LyBrLLpechH246YYJ1kIDPa8RresfhJeIHg5zS4A==", + "dependencies": { + "doctrine": "^2.0.0", + "doctrine-file": "^1.0.2", + "express-swaggerize-ui": "^1.0.3", + "glob": "^7.0.3", + "recursive-iterator": "^2.0.3", + "swagger-parser": "^5.0.5" + } + }, + "node_modules/express-swagger-generator/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/express-swaggerize-ui": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/express-swaggerize-ui/-/express-swaggerize-ui-1.1.0.tgz", + "integrity": "sha512-dDJuWV/GlISNYyKvFMa3EDr6sYzMgMrVRCt9o1kQxaIIKnmK1NJvaTzGbRIokIlGGHriIT6E2ztorRyRxLuOzA==", + "dependencies": { + "express": "^4.13.3" + } + }, "node_modules/express/node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -3787,6 +3384,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3795,8 +3405,7 @@ "node_modules/fast-diff": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==" }, "node_modules/fast-glob": { "version": "3.3.1", @@ -3836,20 +3445,25 @@ "reusify": "^1.0.4" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "dependencies": { - "bser": "2.1.1" - } - }, "node_modules/fecha": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -3898,16 +3512,26 @@ } }, "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dependencies": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "bin": { + "flat": "cli.js" } }, "node_modules/flat-cache": { @@ -3952,6 +3576,14 @@ } } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -3965,6 +3597,11 @@ "node": ">= 6" } }, + "node_modules/format-util": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/format-util/-/format-util-1.0.5.tgz", + "integrity": "sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg==" + }, "node_modules/formidable": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", @@ -3995,6 +3632,19 @@ "node": ">= 0.6" } }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -4022,24 +3672,36 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gauge": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", @@ -4059,24 +3721,22 @@ "node": ">=10" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "engines": { + "node": "*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", @@ -4091,20 +3751,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, "engines": { "node": ">=10" }, @@ -4112,6 +3762,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -4142,13 +3807,18 @@ "node": ">= 6" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dependencies": { + "define-properties": "^1.1.3" + }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/globby": { @@ -4170,17 +3840,47 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -4192,13 +3892,31 @@ "node": ">= 0.4.0" } }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "engines": { - "node": ">=4" + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { @@ -4223,11 +3941,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, "node_modules/helmet": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/helmet/-/helmet-4.6.0.tgz", @@ -4256,24 +3996,6 @@ "node": ">=0.10.0" } }, - "node_modules/html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^1.0.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -4289,43 +4011,6 @@ "node": ">= 0.8" } }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": 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", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/http-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/http-status-codes": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.2.0.tgz", @@ -4368,7 +4053,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, "engines": { "node": ">=10.17.0" } @@ -4377,7 +4061,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", - "dev": true, "bin": { "husky": "lib/bin.js" }, @@ -4430,25 +4113,6 @@ "node": ">=4" } }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -4471,6 +4135,19 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ip": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", @@ -4484,11 +4161,50 @@ "node": ">= 0.10" } }, - "node_modules/is-arrayish": { - "version": "0.3.2", + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -4500,6 +4216,32 @@ "node": ">=8" } }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { "version": "2.13.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", @@ -4511,11 +4253,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-docker": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, "bin": { "is-docker": "cli.js" }, @@ -4542,15 +4297,6 @@ "node": ">=8" } }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -4566,7 +4312,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, "dependencies": { "is-docker": "^3.0.0" }, @@ -4580,723 +4325,288 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "engines": { - "node": ">=8" + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "engines": { - "node": ">=8" + "node": ">=0.12.0" } }, - "node_modules/is-wsl/node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "engines": { "node": ">=8" } }, - "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "engines": { "node": ">=8" } }, - "node_modules/istanbul-lib-instrument/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/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" + "node": ">= 0.4" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/istanbul-lib-source-maps/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", "dependencies": { - "ms": "2.1.2" + "call-bind": "^1.0.2" }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/istanbul-lib-source-maps/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", - "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", - "dev": true, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dependencies": { - "@jest/core": "^27.5.1", - "import-local": "^3.0.2", - "jest-cli": "^27.5.1" - }, - "bin": { - "jest": "bin/jest.js" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-changed-files": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", - "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", - "dev": true, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dependencies": { - "@jest/types": "^27.5.1", - "execa": "^5.0.0", - "throat": "^6.0.1" + "has-symbols": "^1.0.2" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-circus": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", - "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", - "dev": true, - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" + "node": ">= 0.4" }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-cli": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", - "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", - "dev": true, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", "dependencies": { - "@jest/core": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "prompts": "^2.0.1", - "yargs": "^16.2.0" - }, - "bin": { - "jest": "bin/jest.js" + "which-typed-array": "^1.1.11" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-config": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", - "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "ts-node": ">=9.0.0" + "node": ">=10" }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", - "dev": true, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "call-bind": "^1.0.2" }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-docblock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", - "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", - "dev": true, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dependencies": { - "detect-newline": "^3.0.0" + "is-docker": "^2.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=8" } }, - "node_modules/jest-each": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", - "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1" + "node_modules/is-wsl/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-environment-jsdom": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", - "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", - "dev": true, - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1", - "jsdom": "^16.6.0" + "node": ">=8" }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-environment-node": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", - "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", - "dev": true, - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" }, - "node_modules/jest-get-type": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", - "dev": true, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/iterate-iterator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", + "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-haste-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", - "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", - "dev": true, + "node_modules/iterate-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", + "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", "dependencies": { - "@jest/types": "^27.5.1", - "@types/graceful-fs": "^4.1.2", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^27.5.1", - "jest-serializer": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "micromatch": "^4.0.4", - "walker": "^1.0.7" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "es-get-iterator": "^1.0.2", + "iterate-iterator": "^1.0.1" }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-jasmine2": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", - "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", - "dev": true, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "throat": "^6.0.1" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-leak-detector": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", - "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", - "dev": true, - "dependencies": { - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", - "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", - "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-mock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", - "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", - "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", - "dev": true, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", - "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", - "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-snapshot": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-runner": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", - "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", - "dev": true, - "dependencies": { - "@jest/console": "^27.5.1", - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-leak-detector": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", - "dev": true, - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-serializer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", - "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", - "dev": true, - "dependencies": { - "@types/node": "*", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", - "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.7.2", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^27.5.1", - "semver": "^7.3.2" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", - "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dependencies": { - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -5304,105 +4614,18 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-validate": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", - "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "leven": "^3.1.0", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watcher": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", - "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", - "dev": true, - "dependencies": { - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^27.5.1", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -5411,135 +4634,35 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsdom/node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/jsdom/node_modules/form-data": { + "node_modules/json-buffer": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, - "node_modules/jsdom/node_modules/tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, + "node_modules/json-schema-ref-parser": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-5.1.3.tgz", + "integrity": "sha512-CpDFlBwz/6la78hZxyB9FECVKGYjIIl3Ms3KLqFj99W7IIb7D00/RDgc++IGB4BBALl0QRhh5m4q5WNSopvLtQ==", + "deprecated": "Please switch to @apidevtools/json-schema-ref-parser", "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jsdom/node_modules/webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true, - "engines": { - "node": ">=10.4" + "call-me-maybe": "^1.0.1", + "debug": "^3.1.0", + "js-yaml": "^3.12.0", + "ono": "^4.0.6" } }, - "node_modules/jsdom/node_modules/whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, + "node_modules/json-schema-ref-parser/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" + "ms": "^2.1.1" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "node_modules/json-schema-ref-parser/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -5559,9 +4682,33 @@ "json5": "lib/cli.js" }, "engines": { - "node": ">=6" + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonschema": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", + "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==", + "engines": { + "node": "*" } }, + "node_modules/jsonschema-draft4": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jsonschema-draft4/-/jsonschema-draft4-1.0.0.tgz", + "integrity": "sha512-sBV3UnQPRiyCTD6uzY/Oao2Yohv6KKgQq7zjPwjFHeR6scg/QSXnzDxdugsGaLQDmFUrUlTbMYdEE+72PizhGA==" + }, "node_modules/jsonwebtoken": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", @@ -5623,29 +4770,11 @@ "json-buffer": "3.0.1" } }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -5662,22 +4791,14 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, "engines": { "node": ">=10" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, "node_modules/lint-staged": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-14.0.1.tgz", "integrity": "sha512-Mw0cL6HXnHN1ag0mN/Dg4g6sr8uf8sn98w2Oc1ECtFto9tvRF7nkXGJRbx8gPlHyoR0pLyBr2lQHbWwmUHe1Sw==", - "dev": true, "dependencies": { "chalk": "5.3.0", "commander": "11.0.0", @@ -5704,7 +4825,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -5716,7 +4836,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -5733,7 +4852,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.1", @@ -5756,7 +4874,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, "engines": { "node": ">=14.18.0" } @@ -5765,7 +4882,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -5777,7 +4893,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, "engines": { "node": ">=12" }, @@ -5788,14 +4903,12 @@ "node_modules/lint-staged/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/lint-staged/node_modules/npm-run-path": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, "dependencies": { "path-key": "^4.0.0" }, @@ -5810,7 +4923,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, "dependencies": { "mimic-fn": "^4.0.0" }, @@ -5825,7 +4937,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -5837,7 +4948,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, "engines": { "node": ">=12" }, @@ -5849,7 +4959,6 @@ "version": "6.6.1", "resolved": "https://registry.npmjs.org/listr2/-/listr2-6.6.1.tgz", "integrity": "sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg==", - "dev": true, "dependencies": { "cli-truncate": "^3.1.0", "colorette": "^2.0.20", @@ -5874,7 +4983,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "engines": { "node": ">=12" }, @@ -5886,7 +4994,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, "engines": { "node": ">=12" }, @@ -5897,14 +5004,12 @@ "node_modules/listr2/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/listr2/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -5921,7 +5026,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -5936,7 +5040,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -5950,15 +5053,17 @@ } }, "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dependencies": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { @@ -5966,6 +5071,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" + }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -5976,6 +5086,11 @@ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, "node_modules/lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", @@ -5996,27 +5111,40 @@ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==" + }, "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/log-update": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz", "integrity": "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==", - "dev": true, "dependencies": { "ansi-escapes": "^5.0.0", "cli-cursor": "^4.0.0", @@ -6035,7 +5163,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", - "dev": true, "dependencies": { "type-fest": "^1.0.2" }, @@ -6050,7 +5177,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "engines": { "node": ">=12" }, @@ -6062,7 +5188,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, "engines": { "node": ">=12" }, @@ -6073,14 +5198,12 @@ "node_modules/log-update/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/log-update/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -6097,7 +5220,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -6112,7 +5234,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, "engines": { "node": ">=10" }, @@ -6124,7 +5245,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -6155,6 +5275,26 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/loglevel": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz", + "integrity": "sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==", + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "node_modules/loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dependencies": { + "get-func-name": "^2.0.0" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -6166,35 +5306,11 @@ "node": ">=10" } }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "dependencies": { - "tmpl": "1.0.5" - } - }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -6209,6 +5325,11 @@ "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", "optional": true }, + "node_modules/merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==" + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -6217,8 +5338,7 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/merge2": { "version": "1.4.1", @@ -6282,7 +5402,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -6348,6 +5467,155 @@ "node": ">=10" } }, + "node_modules/mocha": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/mocha/node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/moment": { "version": "2.29.4", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", @@ -6502,6 +5770,25 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6515,6 +5802,11 @@ "node": ">= 0.6" } }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, "node_modules/node-addon-api": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", @@ -6558,17 +5850,19 @@ "webidl-conversions": "^3.0.0" } }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", - "dev": true + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } }, "node_modules/normalize-path": { "version": "3.0.0", @@ -6582,7 +5876,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -6601,12 +5894,6 @@ "set-blocking": "^2.0.0" } }, - "node_modules/nwsapi": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", - "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", - "dev": true - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -6631,6 +5918,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -6670,7 +5982,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -6681,11 +5992,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ono": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/ono/-/ono-4.0.11.tgz", + "integrity": "sha512-jQ31cORBFE6td25deYeD80wxKBMj+zBmHTrVxnc6CKhx8gho6ipmWM5zj/oeoqioZ99yqBls9Z/9Nss7J26G2g==", + "dependencies": { + "format-util": "^1.0.3" + } + }, "node_modules/open": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", - "dev": true, "dependencies": { "default-browser": "^4.0.0", "define-lazy-prop": "^3.0.0", @@ -6699,6 +6017,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openapi-schema-validation": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/openapi-schema-validation/-/openapi-schema-validation-0.4.2.tgz", + "integrity": "sha512-K8LqLpkUf2S04p2Nphq9L+3bGFh/kJypxIG2NVGKX0ffzT4NQI9HirhiY6Iurfej9lCu7y4Ndm4tv+lm86Ck7w==", + "dependencies": { + "jsonschema": "1.2.4", + "jsonschema-draft4": "^1.0.0", + "swagger-schema-official": "2.0.0-bab6bed" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "peer": true + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -6715,6 +6049,14 @@ "node": ">= 0.8.0" } }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -6730,41 +6072,19 @@ } }, "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dependencies": { - "p-try": "^2.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6776,30 +6096,6 @@ "node": ">=6" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -6850,11 +6146,18 @@ "node": ">=8" } }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "engines": { + "node": "*" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -6871,7 +6174,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true, "bin": { "pidtree": "bin/pidtree.js" }, @@ -6879,27 +6181,6 @@ "node": ">=0.10" } }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6912,7 +6193,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", - "dev": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -6927,7 +6207,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, "dependencies": { "fast-diff": "^1.1.2" }, @@ -6936,24 +6215,22 @@ } }, "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dependencies": { - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "react-is": "^18.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, "engines": { "node": ">=10" }, @@ -6961,17 +6238,24 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, + "node_modules/promise.any": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/promise.any/-/promise.any-2.0.6.tgz", + "integrity": "sha512-Ew/MrPtTjiHnnki0AA2hS2o65JaZ5n+5pp08JSyWWUdeOGF4F41P+Dn+rdqnaOV/FTxhR6eBDX412luwn3th9g==", "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" + "array.prototype.map": "^1.0.5", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-aggregate-error": "^1.0.10", + "get-intrinsic": "^1.2.1", + "iterate-value": "^1.0.2" }, "engines": { - "node": ">= 6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/proxy-addr": { @@ -6991,12 +6275,6 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -7019,12 +6297,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -7044,6 +6316,14 @@ } ] }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -7067,10 +6347,9 @@ } }, "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/readable-stream": { "version": "3.6.2", @@ -7096,21 +6375,40 @@ "node": ">=8.10.0" } }, + "node_modules/recursive-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/recursive-iterator/-/recursive-iterator-2.0.3.tgz", + "integrity": "sha512-SqfNKjjTw7Lq3E2S6P8L5Ac7YFD91mbkzWRlxrWK4tWioJRKDhe1+PtWS0X0hkQNEzZDpSish0TTXAVM4cRUzQ==" + }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, "node_modules/resolve": { "version": "1.22.4", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", @@ -7127,41 +6425,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve.exports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", - "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/restore-cursor": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "dev": true, "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -7185,8 +6452,7 @@ "node_modules/rfdc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" }, "node_modules/rimraf": { "version": "3.0.2", @@ -7206,7 +6472,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dev": true, "dependencies": { "execa": "^5.0.0" }, @@ -7217,6 +6482,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7239,6 +6512,23 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -7258,6 +6548,19 @@ } ] }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-stable-stringify": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", @@ -7271,18 +6574,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "node_modules/saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -7325,6 +6616,14 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -7344,6 +6643,19 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -7399,12 +6711,6 @@ "is-arrayish": "^0.3.1" } }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -7417,7 +6723,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" @@ -7433,7 +6738,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, "engines": { "node": ">=12" }, @@ -7445,7 +6749,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -7518,7 +6821,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, "dependencies": { "escape-string-regexp": "^2.0.0" }, @@ -7526,6 +6828,14 @@ "node": ">=10" } }, + "node_modules/stack-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/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -7534,6 +6844,17 @@ "node": ">= 0.8" } }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -7546,24 +6867,10 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", - "dev": true, "engines": { "node": ">=0.6.19" } }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -7577,6 +6884,48 @@ "node": ">=8" } }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -7589,19 +6938,17 @@ } }, "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, "engines": { "node": ">=6" } @@ -7682,73 +7029,134 @@ } }, "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==", - "dev": true, + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "dev": true, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swagger-jsdoc": { + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", + "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" + "commander": "6.2.0", + "doctrine": "3.0.0", + "glob": "7.1.6", + "lodash.mergewith": "^4.6.2", + "swagger-parser": "^10.0.3", + "yaml": "2.0.0-1" + }, + "bin": { + "swagger-jsdoc": "bin/swagger-jsdoc.js" }, "engines": { - "node": ">=8" + "node": ">=12.0.0" } }, - "node_modules/supports-hyperlinks/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, + "node_modules/swagger-jsdoc/node_modules/commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/supports-hyperlinks/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "node_modules/swagger-jsdoc/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dependencies": { - "has-flag": "^4.0.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=8" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" + "node_modules/swagger-jsdoc/node_modules/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", + "dependencies": { + "@apidevtools/swagger-parser": "10.0.3" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=10" + } + }, + "node_modules/swagger-jsdoc/node_modules/yaml": { + "version": "2.0.0-1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", + "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", + "engines": { + "node": ">= 6" } }, - "node_modules/swagger-autogen": { - "version": "2.23.5", - "resolved": "https://registry.npmjs.org/swagger-autogen/-/swagger-autogen-2.23.5.tgz", - "integrity": "sha512-4Tl2+XhZMyHoBYkABnScHtQE0lKPKUD3NBt09mClrI6UKOUYljKlYw1xiFVwsHCTGR2hAXmhT4PpgjruCtt1ZA==", + "node_modules/swagger-methods": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/swagger-methods/-/swagger-methods-1.0.8.tgz", + "integrity": "sha512-G6baCwuHA+C5jf4FNOrosE4XlmGsdjbOjdBK4yuiDDj/ro9uR4Srj3OR84oQMT8F3qKp00tYNv0YN730oTHPZA==", + "deprecated": "This package is no longer being maintained." + }, + "node_modules/swagger-parser": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-5.0.6.tgz", + "integrity": "sha512-FdzCYFK11iGgrOpojlqUluU6SKThtzmu+5Get+6ValJR2TFwTnES1x4Fdfgy3C4/8VVXk4Va/WsqGlbyY/Os+A==", + "dependencies": { + "call-me-maybe": "^1.0.1", + "debug": "^3.1.0", + "json-schema-ref-parser": "^5.1.3", + "ono": "^4.0.6", + "openapi-schema-validation": "^0.4.2", + "swagger-methods": "^1.0.4", + "swagger-schema-official": "2.0.0-bab6bed", + "z-schema": "^3.23.0" + } + }, + "node_modules/swagger-parser/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dependencies": { - "acorn": "^7.4.1", - "deepmerge": "^4.2.2", - "glob": "^7.1.7", - "json5": "^2.2.3" + "ms": "^2.1.1" } }, + "node_modules/swagger-parser/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/swagger-schema-official": { + "version": "2.0.0-bab6bed", + "resolved": "https://registry.npmjs.org/swagger-schema-official/-/swagger-schema-official-2.0.0-bab6bed.tgz", + "integrity": "sha512-rCC0NWGKr/IJhtRuPq/t37qvZHI/mH4I4sxflVM+qgVe5Z2uOCivzWaVbuioJaB61kvm5UvB7b49E+oBY0M8jA==" + }, "node_modules/swagger-ui-dist": { "version": "5.4.2", "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.4.2.tgz", @@ -7768,17 +7176,10 @@ "express": ">=4.0.0 || >=5.0.0-beta" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, "node_modules/synckit": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", - "dev": true, "dependencies": { "@pkgr/utils": "^2.3.1", "tslib": "^2.5.0" @@ -7791,9 +7192,9 @@ } }, "node_modules/tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -7806,36 +7207,6 @@ "node": ">=10" } }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", @@ -7846,17 +7217,10 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" }, - "node_modules/throat": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", - "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==", - "dev": true - }, "node_modules/titleize": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -7864,19 +7228,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, "engines": { - "node": ">=4" + "node": ">=0.6.0" } }, "node_modules/to-regex-range": { @@ -7898,21 +7258,6 @@ "node": ">=0.6" } }, - "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/tr46": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", @@ -7941,9 +7286,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.2.tgz", - "integrity": "sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", "engines": { "node": ">=16.13.0" }, @@ -7951,47 +7296,96 @@ "typescript": ">=4.2.0" } }, - "node_modules/ts-jest": { - "version": "27.1.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.5.tgz", - "integrity": "sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA==", - "dev": true, + "node_modules/ts-mocha": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/ts-mocha/-/ts-mocha-10.0.0.tgz", + "integrity": "sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw==", "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^27.0.0", - "json5": "2.x", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "20.x" + "ts-node": "7.0.1" }, "bin": { - "ts-jest": "cli.js" + "ts-mocha": "bin/ts-mocha" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">= 6.X.X" + }, + "optionalDependencies": { + "tsconfig-paths": "^3.5.0" }, "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@types/jest": "^27.0.0", - "babel-jest": ">=27.0.0 <28", - "jest": "^27.0.0", - "typescript": ">=3.8 <5.0" + "mocha": "^3.X.X || ^4.X.X || ^5.X.X || ^6.X.X || ^7.X.X || ^8.X.X || ^9.X.X || ^10.X.X" + } + }, + "node_modules/ts-mocha/node_modules/diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/ts-mocha/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==", + "optional": true, + "dependencies": { + "minimist": "^1.2.0" }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@types/jest": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/ts-mocha/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ts-mocha/node_modules/ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "dependencies": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + }, + "bin": { + "ts-node": "dist/bin.js" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ts-mocha/node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "optional": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/ts-mocha/node_modules/yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ==", + "engines": { + "node": ">=4" } }, "node_modules/ts-node": { @@ -8114,7 +7508,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", - "dev": true, "dependencies": { "json5": "^2.2.2", "minimist": "^1.2.6", @@ -8124,23 +7517,6 @@ "node": ">=6" } }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/tsconfig/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "engines": { - "node": ">=4" - } - }, "node_modules/tsconfig/node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -8152,8 +7528,23 @@ "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/tsoa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tsoa/-/tsoa-5.1.1.tgz", + "integrity": "sha512-U6+5CyD3+u9Dtza0fBnv4+lgmbZEskYljzRpKf3edGCAGtMKD2rfjtDw9jUdTfWb1FEDvsnR3pRvsSGBXaOdsA==", + "dependencies": { + "@tsoa/cli": "^5.1.1", + "@tsoa/runtime": "^5.0.0" + }, + "bin": { + "tsoa": "dist/cli.js" + }, + "engines": { + "node": ">=12.0.0", + "yarn": ">=1.9.4" + } }, "node_modules/type-check": { "version": "0.4.0", @@ -8170,7 +7561,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, "engines": { "node": ">=4" } @@ -8179,7 +7569,6 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, "engines": { "node": ">=10" }, @@ -8199,34 +7588,111 @@ "node": ">= 0.6" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", "dependencies": { - "is-typedarray": "^1.0.0" + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" + } + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "engines": { - "node": ">= 4.0.0" + "node": ">= 10.0.0" } }, "node_modules/unpipe": { @@ -8241,41 +7707,10 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, "engines": { "node": ">=8" } }, - "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -8284,16 +7719,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -8312,29 +7737,6 @@ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" }, - "node_modules/v8-to-istanbul": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", - "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/v8-to-istanbul/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, "node_modules/validator": { "version": "13.11.0", "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", @@ -8351,37 +7753,6 @@ "node": ">= 0.8" } }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", - "dev": true, - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, - "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "dependencies": { - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "dependencies": { - "makeerror": "1.0.12" - } - }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -8390,21 +7761,6 @@ "node": ">=12" } }, - "node_modules/whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "dependencies": { - "iconv-lite": "0.4.24" - } - }, - "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, "node_modules/whatwg-url": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", @@ -8431,6 +7787,39 @@ "node": ">= 8" } }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -8490,21 +7879,27 @@ "node": ">= 6.4.0" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, + "node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==" + }, "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=8" } }, "node_modules/wrappy": { @@ -8512,51 +7907,6 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, "node_modules/xss-clean": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/xss-clean/-/xss-clean-0.1.4.tgz", @@ -8583,7 +7933,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "engines": { "node": ">=10" } @@ -8597,7 +7946,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", - "dev": true, "engines": { "node": ">= 14" } @@ -8619,7 +7967,6 @@ "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -8634,10 +7981,23 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, "engines": { "node": ">=10" } @@ -8660,6 +8020,37 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/z-schema": { + "version": "3.25.1", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-3.25.1.tgz", + "integrity": "sha512-7tDlwhrBG+oYFdXNOjILSurpfQyuVgkRe3hB2q8TEssamDHB7BbLWYkYO98nTn0FibfdFroFKDjndbgufAgS/Q==", + "dependencies": { + "core-js": "^2.5.7", + "lodash.get": "^4.0.0", + "lodash.isequal": "^4.0.0", + "validator": "^10.0.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "optionalDependencies": { + "commander": "^2.7.1" + } + }, + "node_modules/z-schema/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==", + "optional": true + }, + "node_modules/z-schema/node_modules/validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==", + "engines": { + "node": ">= 0.10" + } } } } diff --git a/backend-app/package.json b/backend-app/package.json index 78452a7..2d6c2a6 100644 --- a/backend-app/package.json +++ b/backend-app/package.json @@ -5,62 +5,78 @@ "main": "app.ts", "scripts": { "debug": "ndb server.ts", - "dev": "ts-node-dev server.ts", - "prod": "node server.ts NODE_ENV=PRODUCTION", - "start": "ts-node-dev server.ts", - "test": "jest --detectOpenHandles", - "prepare": "cd .. && husky install" + "start": "nodemon", + "start:build": "node build/server.js", + "test": "ts-mocha --bail", + "test:build": "cd ./build && mocha --bail", + "clean": "tsc --build --clean", + "build": "tsc", + "generate": "tsoa spec-and-routes && tsoa swagger", + "seed": "ts-node-dev ./seeds/m.js" }, - "author": "Bella Abdelouahab", + "author": "NFS-Team", "license": "ISC", "dependencies": { - "@typescript-eslint/parser": "6.5.0", + "@inquirer/prompts": "3.1.1", + "@typegoose/typegoose": "11.5.0", + "@types/bcrypt": "5.0.0", + "@types/chai": "4.3.6", + "@types/compression": "1.7.3", + "@types/cookie-parser": "1.4.4", + "@types/cors": "2.8.14", + "@types/expect": "24.3.0", + "@types/express": "4.17.17", + "@types/express-routes-versioning": "1.0.1", + "@types/hpp": "0.2.3", + "@types/jsonwebtoken": "9.0.3", + "@types/mocha": "10.0.2", + "@types/morgan": "1.9.5", + "@types/node": "^16.11.7", + "@types/supertest": "2.0.13", + "@types/swagger-jsdoc": "6.0.1", + "@types/swagger-ui-express": "4.1.3", + "@types/validator": "13.11.1", + "@typescript-eslint/parser": "6.7.2", "axios": "1.5.0", "bcrypt": "5.1.1", + "chai": "4.3.10", "compression": "1.7.4", "cookie-parser": "^1.4.5", "cors": "^2.8.5", "dotenv": "16.3.1", - "express": "^4.17.1", + "eslint": "8.48.0", + "eslint-config-prettier": "9.0.0", + "eslint-plugin-prettier": "5.0.0", + "express": "4.18.2", "express-bearer-token": "2.4.0", "express-mongo-sanitize": "2.2.0", "express-rate-limit": "6.10.0", "express-routes-versioning": "1.0.1", + "express-swagger-generator": "1.1.17", "helmet": "4.6.0", "hpp": "0.2.3", "http-status-codes": "2.2.0", + "husky": "7.0.4", "jsonwebtoken": "9.0.2", + "lint-staged": "14.0.1", + "mocha": "10.2.0", "mongoose": "7.5.0", "morgan": "1.10.0", + "prettier": "3.0.3", "qs": "6.11.2", "supertest": "6.3.3", - "swagger-autogen": "2.23.5", + "swagger-jsdoc": "6.2.8", "swagger-ui-express": "5.0.0", + "ts-mocha": "10.0.0", + "ts-node": "^10.4.0", "ts-node-dev": "2.0.0", - "validator": "^13.11.0", + "tsconfig-paths": "4.2.0", + "tsoa": "5.1.1", + "typescript": "5.2.2", + "validator": "13.11.0", "winston": "^3.10.0", "winston-daily-rotate-file": "^4.7.1", - "xss-clean": "^0.1.4", - "yamljs": "^0.3.0" - }, - "devDependencies": { - "@types/body-parser": "^1.19.0", - "@types/cookie-parser": "^1.4.2", - "@types/cors": "^2.8.10", - "@types/express": "^4.17.13", - "@types/helmet": "^4.0.0", - "@types/node": "^16.11.7", - "eslint": "8.48.0", - "eslint-config-prettier": "9.0.0", - "eslint-plugin-prettier": "5.0.0", - "husky": "7.0.4", - "jest": "27.5.1", - "lint-staged": "14.0.1", - "prettier": "3.0.3", - "ts-jest": "^27.1.3", - "ts-node": "^10.4.0", - "tsconfig-paths": "4.2.0", - "typescript": "^4.4.4" + "xss-clean": "^0.1.4" }, "lint-staged": { "*.+(ts|js)": "eslint --fix", diff --git a/backend-app/routes/auth_routes.js b/backend-app/routes/auth_routes.js deleted file mode 100644 index 21d91fb..0000000 --- a/backend-app/routes/auth_routes.js +++ /dev/null @@ -1,19 +0,0 @@ -const authController = require('../controllers/auth_controllers/auth_controller'); -const express = require('express'); -const router = express.Router(); - -router.post('/signup', authController.signup); -router.post('/login', authController.login); -router.delete('/logout', authController.logout); -router.put('/token-refresh', authController.tokenRefresh); -router.get('/activate', authController.activateAccount); -router.patch('/updateMyPassword', authController.updatePassword); -router.patch('/forgotPassword', authController.forgotPassword); -router.get('/github/callback', authController.githubHandler); - -// make this file so i can use it with authRoutes(router) in index.js -const authRoutes = (mainrouter) => { - // swaggergenerator.register('auth', './routes/auth_routes.js'); - mainrouter.use('/auth', router); -}; -module.exports = authRoutes; diff --git a/backend-app/routes/auth_routes.ts b/backend-app/routes/auth_routes.ts new file mode 100644 index 0000000..ef0781c --- /dev/null +++ b/backend-app/routes/auth_routes.ts @@ -0,0 +1,20 @@ +import * as authController from '../controllers/auth_controllers/auth_controller'; +import * as password_management from '../controllers/auth_controllers/password_management'; +import express, { Router } from 'express'; + +const router = express.Router(); + +router.post('/signup', authController.signup); +router.post('/login', authController.login); +router.delete('/logout', authController.logout); +router.get('/refreshToken', authController.tokenRefresh); +router.get('/activate', authController.activateAccount); +router.patch('/forgotPassword', password_management.forgotPassword); +router.patch('/updateMyPassword', password_management.updatePassword); +router.get('/github/callback', authController.githubHandler); + +const authRoutes = (mainrouter: Router) => { + mainrouter.use('/auth', router); +}; + +export default authRoutes; diff --git a/backend-app/routes/github_routes.ts b/backend-app/routes/github_routes.ts index c93bc9c..0b01e88 100644 --- a/backend-app/routes/github_routes.ts +++ b/backend-app/routes/github_routes.ts @@ -4,8 +4,13 @@ import * as githubController from '../controllers/auth_controllers/github_contro router.get('/recent-repo', githubController.getRecentRepo); +/** + * Registers the GitHub routes with the main router and adds them to the Swagger documentation. + * @function + * @name githubRoutes + * @param {Object} mainrouter - Express router object. + */ const githubRoutes = (mainrouter: Router) => { - // swaggergenerator.register('github', './routes/github_routes.js'); mainrouter.use('/github', router); }; diff --git a/backend-app/routes/index.ts b/backend-app/routes/index.ts index 584801b..1b67b28 100644 --- a/backend-app/routes/index.ts +++ b/backend-app/routes/index.ts @@ -4,18 +4,19 @@ import adminRoutes from './users/admin_route'; import superAdminRoutes from './users/super_admin_route'; import authRoutes from './auth_routes'; import githubRoutes from './github_routes'; -import authController from '../controllers/auth_controllers/auth_controller'; +import { protect } from '../controllers/auth_controllers/auth_controller'; const router = Router(); // public routes authRoutes(router); -router.use(authController.protect); +router.use(protect); // protected routes userRoutes(router); adminRoutes(router); superAdminRoutes(router); githubRoutes(router); + export default router; diff --git a/backend-app/routes/users/admin_route.js b/backend-app/routes/users/admin_route.ts similarity index 87% rename from backend-app/routes/users/admin_route.js rename to backend-app/routes/users/admin_route.ts index c679775..bd382bc 100644 --- a/backend-app/routes/users/admin_route.js +++ b/backend-app/routes/users/admin_route.ts @@ -1,5 +1,5 @@ -const express = require('express'); -const { +import { Router } from 'express'; +import { authorizeOrRestrict, banUser, unbanUser, @@ -10,17 +10,18 @@ const { deleteRole, assignRoleToUser, removeRoleFromUser, -} = require('../../controllers/users_controllers/admin_controller'); -const authController = require('../../controllers/auth_controllers/auth_controller'); -const { restrictTo } = require('../../middlewares/authorization'); -const router = express.Router(); -const Actions = require('../../constants/actions'); -const userController = require('../../controllers/users_controllers/user_controller'); +} from '../../controllers/users_controllers/admin_controller'; +import * as authController from '../../controllers/auth_controllers/auth_controller'; +import restrictTo from '../../middlewares/authorization'; +import Actions from '../../constants/actions'; +import * as userController from '@controllers/users_controllers/user_controller'; /** * Below all routes are protected */ +const router = Router(); + router.use(authController.restrictTo('ADMIN', 'SUPER_ADMIN')); router @@ -141,8 +142,8 @@ router.put( removeRoleFromUser ); -adminRoutes = (mainrouter) => { +const adminRoutes = (mainrouter: Router) => { // swaggergenerator.register('admin', './routes/users/admin_route.js'); mainrouter.use('/admin', router); }; -module.exports = adminRoutes; +export default adminRoutes; diff --git a/backend-app/routes/users/super_admin_route.js b/backend-app/routes/users/super_admin_route.ts similarity index 77% rename from backend-app/routes/users/super_admin_route.js rename to backend-app/routes/users/super_admin_route.ts index d8f17bc..efa9347 100644 --- a/backend-app/routes/users/super_admin_route.js +++ b/backend-app/routes/users/super_admin_route.ts @@ -1,14 +1,16 @@ -const express = require('express'); -const router = express.Router(); -const authController = require('../../controllers/auth_controllers/auth_controller'); -const { restrictTo } = require('../../middlewares/authorization'); -const Actions = require('../../constants/actions'); -const { +import express from 'express'; +import { Router } from 'express'; +import * as authController from '../../controllers/auth_controllers/auth_controller'; +import restrictTo from '../../middlewares/authorization'; +import Actions from '../../constants/actions'; +import { addSuperAdmin, removeSuperAdmin, addAdmin, removeAdmin, -} = require('../../controllers/users_controllers/admin_controller'); +} from '../../controllers/users_controllers/admin_controller'; + +const router = Router(); router.use(authController.restrictTo('SUPER_ADMIN')); @@ -60,11 +62,11 @@ router.put( removeAdmin ); -superAdminRoutes = (mainrouter) => { +const superAdminRoutes = (mainrouter: express.Router) => { // swaggergenerator.register( // 'super_admin', // './routes/users/super_admin_route.js' // ); mainrouter.use('/super_admin', router); }; -module.exports = superAdminRoutes; +export default superAdminRoutes; diff --git a/backend-app/routes/users/user_route.ts b/backend-app/routes/users/user_route.ts index b13ab38..a056b42 100644 --- a/backend-app/routes/users/user_route.ts +++ b/backend-app/routes/users/user_route.ts @@ -1,15 +1,36 @@ import { Router } from 'express'; -import userController from '../../controllers/users_controllers/user_controller'; +import * as userController from '@controllers/users_controllers/user_controller'; const router = Router(); router .route('/me') + /** + * @swagger + * /api/useron: + * get: + * summary: Get a list of users + * description: Retrieve a list of users from the database. + * requestBody: + * description: Optional description in *Markdown* + * required: false + * responses: + * 200: + * description: A list of users. + * content: + * application/json: + * example: + * - id: 1 + * name: John Doe + * - id: 2 + * name: Jane Smith + * x-swagger-jsdoc: + * tryItOutEnabled: true // Enable "Try it out" by default + */ .get(userController.getMe) .delete(userController.deleteMe) .patch(userController.updateMe); const userRoutes = (mainrouter: Router) => { - // swaggergenerator.register('user', './routes/users/user_route.js'); mainrouter.use('/users', router); }; diff --git a/backend-app/seed/setup_seed.js b/backend-app/seed/setup_seed.js deleted file mode 100644 index 3ed4e86..0000000 --- a/backend-app/seed/setup_seed.js +++ /dev/null @@ -1,6 +0,0 @@ -const mongoose = require('mongoose'); - -mongoose.connect(process.env.MONGO_URI, { - useNewUrlParser: true, - useUnifiedTopology: true, -}); diff --git a/backend-app/seedData.js b/backend-app/seedData.js deleted file mode 100644 index e69de29..0000000 diff --git a/backend-app/seeds/index.ts b/backend-app/seeds/index.ts new file mode 100644 index 0000000..fd76f18 --- /dev/null +++ b/backend-app/seeds/index.ts @@ -0,0 +1,19 @@ +function seed() { + try { + // Connect to the database + // await connectDatabase(); + + // // Run individual seed scripts + // await seedUsers(); + // await seedProducts(); + + // // Disconnect from the database + // await disconnectDatabase(); + + console.log('Seeding completed successfully.'); + } catch (error) { + console.error('Error seeding the database:', error); + } +} + +seed(); diff --git a/backend-app/seeds/setup_seed.ts b/backend-app/seeds/setup_seed.ts new file mode 100644 index 0000000..3538193 --- /dev/null +++ b/backend-app/seeds/setup_seed.ts @@ -0,0 +1,108 @@ +import mongoose from 'mongoose'; +import '../utils/register_paths'; +import Role from '../models/user/role_model'; +import User from '../models/user/user_model'; +import logger from '@utils/logger'; +import { DATABASE, ADMIN_EMAIL, ADMIN_PASSWORD } from '@config/app_config'; +import Actions from '@constants/actions'; + +// Connect to MongoDB + +async function seed() { + await mongoose + .connect( + DATABASE as string, + { + useNewUrlParser: true, + useUnifiedTopology: true, + } as mongoose.ConnectOptions + ) + .then(() => console.log('Connected to MongoDB')) + .catch((err: any) => console.error(err)); + + interface Role { + name: string; + authorities: Array; + restrictions: Array; + } + + const Roles: { [key: string]: Role } = { + SUPER_ADMIN: { + name: 'SUPER_ADMIN', + authorities: Object.values(Actions), + restrictions: [], + }, + ADMIN: { + name: 'ADMIN', + authorities: [ + Actions.DELETE_USER, + Actions.UPDATE_USER, + Actions.BAN_USER, + ], + restrictions: [], + }, + USER: { + name: 'USER', + authorities: [Actions.UPDATE_CALANDER], + restrictions: [], + }, + }; + Object.freeze(Roles); + + // Seed default roles + async function seedRoles() { + const roles = await Role.find(); + if (roles.length === 0) { + for (const role of Object.values(Roles)) { + await Role.create(role); + } + logger.info('Roles seeded'); + } else { + logger.info('Roles already seeded'); + } + } + + // seed default users + const createAdminUser = async () => { + try { + const user = await User.findOne({ email: ADMIN_EMAIL }); + if (!user) { + // make sure super admin role is created if not created throw error + const superAdminRole = await Role.findOne({ + name: 'SUPER_ADMIN', + }); + if (!superAdminRole) { + throw new Error('Super Admin role not found'); + } + await User.create({ + name: 'Supper Admin', + email: ADMIN_EMAIL, + password: ADMIN_PASSWORD, + roles: [superAdminRole._id], + authorities: superAdminRole.authorities, + restrictions: superAdminRole.restrictions, + active: true, + }); + } else { + logger.info('default users already created'); + } + } catch (err) { + logger.error(err.stack); + } + }; + + // create a default normal user + + await seedRoles(); + await createAdminUser(); +} + +seed() + .then(() => { + mongoose.disconnect(); + logger.info('Seeding completed successfully.'); + }) + .catch((err) => { + logger.error('Error seeding the database:', err); + mongoose.disconnect(); + }); diff --git a/backend-app/seed/users.json b/backend-app/seeds/users.json similarity index 100% rename from backend-app/seed/users.json rename to backend-app/seeds/users.json diff --git a/backend-app/server.ts b/backend-app/server.ts index 82970a2..c88549e 100644 --- a/backend-app/server.ts +++ b/backend-app/server.ts @@ -1,14 +1,13 @@ import mongoose from 'mongoose'; import './utils/register_paths'; - -import '@utils/logger'; +import logger from '@utils/logger'; import fs from 'fs'; import { DATABASE, PORT } from './config/app_config'; -import createRoles from './utils/authorization/role/create_roles'; +import createRoles from './utils/authorization/roles/create_roles'; process.on('uncaughtException', (err) => { - Logger.error('UNCAUGHT EXCEPTION!!! shutting down ...'); - Logger.error(`${err.name}, ${err.message}, ${err.stack}`); + logger.error('UNCAUGHT EXCEPTION!!! shutting down ...'); + logger.error(`${err}, ${err.message}, ${err.stack}`); process.exit(1); }); @@ -16,55 +15,65 @@ import app from './app'; mongoose.set('strictQuery', true); +let expServer: Promise; + // Connect the database mongoose - .connect(DATABASE, { useNewUrlParser: true } as mongoose.ConnectOptions) + .connect( + DATABASE as string, + { useNewUrlParser: true } as mongoose.ConnectOptions + ) .then(() => { - Logger.info('DB Connected Successfully!'); + logger.info('DB Connected Successfully!'); + expServer = startServer(); + logger.info(`Swagger Will Be Available at /docs /docs-json`); }) - .catch((err) => { - Logger.error( + .catch((err: Error) => { + logger.error( 'DB Connection Failed! \n\tException : ' + err + '\n' + err.stack ); - }); //Now all the errors of mongo will be handled by the catch block + }); // When the connection is disconnected mongoose.connection.on('disconnected', () => { - Logger.error('DB Connection Disconnected!'); + logger.error('DB Connection Disconnected!'); }); // Start the server -const expServer = app.listen(PORT, async () => { +const startServer = async (): Promise => { if (!fs.existsSync('.env')) - Logger.warn('.env file not found, using .env.example file'); - Logger.info(`App running on http://localhost:${PORT}`); + logger.warn('.env file not found, using .env.example file'); + logger.info(`App running on http://localhost:${PORT}`); await createRoles(); -}); + return app.listen(PORT); +}; import createDefaultUser from './utils/create_default_user'; createDefaultUser(); process.on('unhandledRejection', (err: Error) => { - Logger.error('UNHANDLED REJECTION!!! shutting down ...'); - Logger.error(`${err.name}, ${err.message}, ${err.stack}`); - expServer.close(() => { - process.exit(1); + logger.error('UNHANDLED REJECTION!!! shutting down ...'); + logger.error(`${err.name}, ${err.message}, ${err.stack}`); + expServer.then((server) => { + server.close(() => { + process.exit(1); + }); }); }); // add graceful shutdown. process.on('SIGTERM', () => { - Logger.info('SIGINT RECEIVED. Shutting down gracefully'); + logger.info('SIGINT RECEIVED. Shutting down gracefully'); mongoose.connection.close(false).then(() => { - Logger.info('💥 Process terminated!'); + logger.info('💥 Process terminated!'); process.exit(0); }); }); process.on('SIGINT', () => { - Logger.info('SIGINT RECEIVED. Shutting down gracefully'); + logger.info('SIGINT RECEIVED. Shutting down gracefully'); mongoose.connection.close(false).then(() => { - Logger.info('💥 Process terminated!'); + logger.info('💥 Process terminated!'); process.exit(0); }); }); diff --git a/backend-app/swagger.json b/backend-app/swagger.json new file mode 100644 index 0000000..d00b129 --- /dev/null +++ b/backend-app/swagger.json @@ -0,0 +1,1304 @@ +{ + "components": { + "examples": {}, + "headers": {}, + "parameters": {}, + "requestBodies": {}, + "responses": {}, + "schemas": { + "Assertion": { + "properties": { + "to": { + "$ref": "#/components/schemas/Assertion" + }, + "be": { + "$ref": "#/components/schemas/Assertion" + }, + "been": { + "$ref": "#/components/schemas/Assertion" + }, + "is": { + "$ref": "#/components/schemas/Assertion" + }, + "that": { + "$ref": "#/components/schemas/Assertion" + }, + "which": { + "$ref": "#/components/schemas/Assertion" + }, + "and": { + "$ref": "#/components/schemas/Assertion" + }, + "has": { + "$ref": "#/components/schemas/Assertion" + }, + "have": { + "$ref": "#/components/schemas/Assertion" + }, + "with": { + "$ref": "#/components/schemas/Assertion" + }, + "at": { + "$ref": "#/components/schemas/Assertion" + }, + "of": { + "$ref": "#/components/schemas/Assertion" + }, + "same": { + "$ref": "#/components/schemas/Assertion" + }, + "but": { + "$ref": "#/components/schemas/Assertion" + }, + "does": { + "$ref": "#/components/schemas/Assertion" + }, + "above": { + "$ref": "#/components/schemas/NumberComparer" + }, + "gt": { + "$ref": "#/components/schemas/NumberComparer" + }, + "greaterThan": { + "$ref": "#/components/schemas/NumberComparer" + }, + "least": { + "$ref": "#/components/schemas/NumberComparer" + }, + "gte": { + "$ref": "#/components/schemas/NumberComparer" + }, + "greaterThanOrEqual": { + "$ref": "#/components/schemas/NumberComparer" + }, + "below": { + "$ref": "#/components/schemas/NumberComparer" + }, + "lt": { + "$ref": "#/components/schemas/NumberComparer" + }, + "lessThan": { + "$ref": "#/components/schemas/NumberComparer" + }, + "most": { + "$ref": "#/components/schemas/NumberComparer" + }, + "lte": { + "$ref": "#/components/schemas/NumberComparer" + }, + "lessThanOrEqual": { + "$ref": "#/components/schemas/NumberComparer" + }, + "instanceof": { + "$ref": "#/components/schemas/InstanceOf" + }, + "instanceOf": { + "$ref": "#/components/schemas/InstanceOf" + }, + "not": { + "$ref": "#/components/schemas/Assertion" + }, + "deep": { + "$ref": "#/components/schemas/Deep" + }, + "ordered": { + "$ref": "#/components/schemas/Ordered" + }, + "nested": { + "$ref": "#/components/schemas/Nested" + }, + "own": { + "$ref": "#/components/schemas/Own" + }, + "any": { + "$ref": "#/components/schemas/KeyFilter" + }, + "all": { + "$ref": "#/components/schemas/KeyFilter" + }, + "a": { + "$ref": "#/components/schemas/Assertion" + }, + "an": { + "$ref": "#/components/schemas/Assertion" + }, + "include": { + "$ref": "#/components/schemas/Include" + }, + "includes": { + "$ref": "#/components/schemas/Include" + }, + "contain": { + "$ref": "#/components/schemas/Include" + }, + "contains": { + "$ref": "#/components/schemas/Include" + }, + "ok": { + "$ref": "#/components/schemas/Assertion" + }, + "true": { + "$ref": "#/components/schemas/Assertion" + }, + "false": { + "$ref": "#/components/schemas/Assertion" + }, + "null": { + "$ref": "#/components/schemas/Assertion" + }, + "undefined": { + "$ref": "#/components/schemas/Assertion" + }, + "NaN": { + "$ref": "#/components/schemas/Assertion" + }, + "exist": { + "$ref": "#/components/schemas/Assertion" + }, + "empty": { + "$ref": "#/components/schemas/Assertion" + }, + "arguments": { + "$ref": "#/components/schemas/Assertion" + }, + "Arguments": { + "$ref": "#/components/schemas/Assertion" + }, + "finite": { + "$ref": "#/components/schemas/Assertion" + }, + "equal": { + "$ref": "#/components/schemas/Equal" + }, + "equals": { + "$ref": "#/components/schemas/Equal" + }, + "eq": { + "$ref": "#/components/schemas/Equal" + }, + "eql": { + "$ref": "#/components/schemas/Equal" + }, + "eqls": { + "$ref": "#/components/schemas/Equal" + }, + "property": { + "$ref": "#/components/schemas/Property" + }, + "ownProperty": { + "$ref": "#/components/schemas/Property" + }, + "haveOwnProperty": { + "$ref": "#/components/schemas/Property" + }, + "ownPropertyDescriptor": { + "$ref": "#/components/schemas/OwnPropertyDescriptor" + }, + "haveOwnPropertyDescriptor": { + "$ref": "#/components/schemas/OwnPropertyDescriptor" + }, + "length": { + "$ref": "#/components/schemas/Length" + }, + "lengthOf": { + "$ref": "#/components/schemas/Length" + }, + "match": { + "$ref": "#/components/schemas/Match" + }, + "matches": { + "$ref": "#/components/schemas/Match" + }, + "keys": { + "$ref": "#/components/schemas/Keys" + }, + "throw": { + "$ref": "#/components/schemas/Throw" + }, + "throws": { + "$ref": "#/components/schemas/Throw" + }, + "Throw": { + "$ref": "#/components/schemas/Throw" + }, + "respondTo": { + "$ref": "#/components/schemas/RespondTo" + }, + "respondsTo": { + "$ref": "#/components/schemas/RespondTo" + }, + "itself": { + "$ref": "#/components/schemas/Assertion" + }, + "satisfy": { + "$ref": "#/components/schemas/Satisfy" + }, + "satisfies": { + "$ref": "#/components/schemas/Satisfy" + }, + "closeTo": { + "$ref": "#/components/schemas/CloseTo" + }, + "approximately": { + "$ref": "#/components/schemas/CloseTo" + }, + "members": { + "$ref": "#/components/schemas/Members" + }, + "increase": { + "$ref": "#/components/schemas/PropertyChange" + }, + "increases": { + "$ref": "#/components/schemas/PropertyChange" + }, + "decrease": { + "$ref": "#/components/schemas/PropertyChange" + }, + "decreases": { + "$ref": "#/components/schemas/PropertyChange" + }, + "change": { + "$ref": "#/components/schemas/PropertyChange" + }, + "changes": { + "$ref": "#/components/schemas/PropertyChange" + }, + "extensible": { + "$ref": "#/components/schemas/Assertion" + }, + "sealed": { + "$ref": "#/components/schemas/Assertion" + }, + "frozen": { + "$ref": "#/components/schemas/Assertion" + }, + "oneOf": { + "$ref": "#/components/schemas/OneOf" + } + }, + "required": [ + "to", + "be", + "been", + "is", + "that", + "which", + "and", + "has", + "have", + "with", + "at", + "of", + "same", + "but", + "does", + "above", + "gt", + "greaterThan", + "least", + "gte", + "greaterThanOrEqual", + "below", + "lt", + "lessThan", + "most", + "lte", + "lessThanOrEqual", + "instanceof", + "instanceOf", + "not", + "deep", + "ordered", + "nested", + "own", + "any", + "all", + "a", + "an", + "include", + "includes", + "contain", + "contains", + "ok", + "true", + "false", + "null", + "undefined", + "NaN", + "exist", + "empty", + "arguments", + "Arguments", + "finite", + "equal", + "equals", + "eq", + "eql", + "eqls", + "property", + "ownProperty", + "haveOwnProperty", + "ownPropertyDescriptor", + "haveOwnPropertyDescriptor", + "length", + "lengthOf", + "match", + "matches", + "keys", + "throw", + "throws", + "Throw", + "respondTo", + "respondsTo", + "itself", + "satisfy", + "satisfies", + "closeTo", + "approximately", + "members", + "increase", + "increases", + "decrease", + "decreases", + "change", + "changes", + "extensible", + "sealed", + "frozen", + "oneOf" + ], + "type": "object", + "additionalProperties": false + }, + "Equal": { + "properties": {}, + "type": "object", + "additionalProperties": false + }, + "Keys": { + "properties": {}, + "type": "object", + "additionalProperties": false + }, + "Deep": { + "properties": { + "keys": { + "$ref": "#/components/schemas/Keys" + }, + "members": { + "$ref": "#/components/schemas/Members" + }, + "be": { + "$ref": "#/components/schemas/Assertion" + }, + "equal": { + "$ref": "#/components/schemas/Equal" + }, + "equals": { + "$ref": "#/components/schemas/Equal" + }, + "eq": { + "$ref": "#/components/schemas/Equal" + }, + "include": { + "$ref": "#/components/schemas/Include" + }, + "includes": { + "$ref": "#/components/schemas/Include" + }, + "contain": { + "$ref": "#/components/schemas/Include" + }, + "contains": { + "$ref": "#/components/schemas/Include" + }, + "property": { + "$ref": "#/components/schemas/Property" + }, + "ordered": { + "$ref": "#/components/schemas/Ordered" + }, + "nested": { + "$ref": "#/components/schemas/Nested" + }, + "oneOf": { + "$ref": "#/components/schemas/OneOf" + }, + "own": { + "$ref": "#/components/schemas/Own" + } + }, + "required": [ + "keys", + "members", + "be", + "equal", + "equals", + "eq", + "include", + "includes", + "contain", + "contains", + "property", + "ordered", + "nested", + "oneOf", + "own" + ], + "type": "object", + "additionalProperties": false + }, + "Members": { + "properties": {}, + "type": "object", + "additionalProperties": false + }, + "Ordered": { + "properties": { + "members": { + "$ref": "#/components/schemas/Members" + } + }, + "required": ["members"], + "type": "object", + "additionalProperties": false + }, + "KeyFilter": { + "properties": { + "keys": { + "$ref": "#/components/schemas/Keys" + }, + "members": { + "$ref": "#/components/schemas/Members" + } + }, + "required": ["keys", "members"], + "type": "object", + "additionalProperties": false + }, + "OneOf": { + "properties": {}, + "type": "object", + "additionalProperties": false + }, + "Include": { + "properties": { + "keys": { + "$ref": "#/components/schemas/Keys" + }, + "deep": { + "$ref": "#/components/schemas/Deep" + }, + "ordered": { + "$ref": "#/components/schemas/Ordered" + }, + "members": { + "$ref": "#/components/schemas/Members" + }, + "any": { + "$ref": "#/components/schemas/KeyFilter" + }, + "all": { + "$ref": "#/components/schemas/KeyFilter" + }, + "oneOf": { + "$ref": "#/components/schemas/OneOf" + } + }, + "required": [ + "keys", + "deep", + "ordered", + "members", + "any", + "all", + "oneOf" + ], + "type": "object", + "additionalProperties": false + }, + "Property": { + "properties": {}, + "type": "object", + "additionalProperties": false + }, + "Nested": { + "properties": { + "include": { + "$ref": "#/components/schemas/Include" + }, + "includes": { + "$ref": "#/components/schemas/Include" + }, + "contain": { + "$ref": "#/components/schemas/Include" + }, + "contains": { + "$ref": "#/components/schemas/Include" + }, + "property": { + "$ref": "#/components/schemas/Property" + }, + "members": { + "$ref": "#/components/schemas/Members" + } + }, + "required": [ + "include", + "includes", + "contain", + "contains", + "property", + "members" + ], + "type": "object", + "additionalProperties": false + }, + "Own": { + "properties": { + "include": { + "$ref": "#/components/schemas/Include" + }, + "includes": { + "$ref": "#/components/schemas/Include" + }, + "contain": { + "$ref": "#/components/schemas/Include" + }, + "contains": { + "$ref": "#/components/schemas/Include" + }, + "property": { + "$ref": "#/components/schemas/Property" + } + }, + "required": [ + "include", + "includes", + "contain", + "contains", + "property" + ], + "type": "object", + "additionalProperties": false + }, + "OwnPropertyDescriptor": { + "properties": {}, + "type": "object", + "additionalProperties": false + }, + "NumberComparer": { + "properties": {}, + "type": "object", + "additionalProperties": false + }, + "Length": { + "properties": { + "to": { + "$ref": "#/components/schemas/Assertion" + }, + "be": { + "$ref": "#/components/schemas/Assertion" + }, + "been": { + "$ref": "#/components/schemas/Assertion" + }, + "is": { + "$ref": "#/components/schemas/Assertion" + }, + "that": { + "$ref": "#/components/schemas/Assertion" + }, + "which": { + "$ref": "#/components/schemas/Assertion" + }, + "and": { + "$ref": "#/components/schemas/Assertion" + }, + "has": { + "$ref": "#/components/schemas/Assertion" + }, + "have": { + "$ref": "#/components/schemas/Assertion" + }, + "with": { + "$ref": "#/components/schemas/Assertion" + }, + "at": { + "$ref": "#/components/schemas/Assertion" + }, + "of": { + "$ref": "#/components/schemas/Assertion" + }, + "same": { + "$ref": "#/components/schemas/Assertion" + }, + "but": { + "$ref": "#/components/schemas/Assertion" + }, + "does": { + "$ref": "#/components/schemas/Assertion" + }, + "above": { + "$ref": "#/components/schemas/NumberComparer" + }, + "gt": { + "$ref": "#/components/schemas/NumberComparer" + }, + "greaterThan": { + "$ref": "#/components/schemas/NumberComparer" + }, + "least": { + "$ref": "#/components/schemas/NumberComparer" + }, + "gte": { + "$ref": "#/components/schemas/NumberComparer" + }, + "greaterThanOrEqual": { + "$ref": "#/components/schemas/NumberComparer" + }, + "below": { + "$ref": "#/components/schemas/NumberComparer" + }, + "lt": { + "$ref": "#/components/schemas/NumberComparer" + }, + "lessThan": { + "$ref": "#/components/schemas/NumberComparer" + }, + "most": { + "$ref": "#/components/schemas/NumberComparer" + }, + "lte": { + "$ref": "#/components/schemas/NumberComparer" + }, + "lessThanOrEqual": { + "$ref": "#/components/schemas/NumberComparer" + } + }, + "required": [ + "to", + "be", + "been", + "is", + "that", + "which", + "and", + "has", + "have", + "with", + "at", + "of", + "same", + "but", + "does", + "above", + "gt", + "greaterThan", + "least", + "gte", + "greaterThanOrEqual", + "below", + "lt", + "lessThan", + "most", + "lte", + "lessThanOrEqual" + ], + "type": "object", + "additionalProperties": false + }, + "Match": { + "properties": {}, + "type": "object", + "additionalProperties": false + }, + "Throw": { + "properties": {}, + "type": "object", + "additionalProperties": false + }, + "RespondTo": { + "properties": {}, + "type": "object", + "additionalProperties": false + }, + "Satisfy": { + "properties": {}, + "type": "object", + "additionalProperties": false + }, + "CloseTo": { + "properties": {}, + "type": "object", + "additionalProperties": false + }, + "PropertyChange": { + "properties": {}, + "type": "object", + "additionalProperties": false + }, + "InstanceOf": { + "properties": {}, + "type": "object", + "additionalProperties": false + }, + "Chai.Assertion": { + "properties": { + "to": { + "$ref": "#/components/schemas/Assertion" + }, + "be": { + "$ref": "#/components/schemas/Assertion" + }, + "been": { + "$ref": "#/components/schemas/Assertion" + }, + "is": { + "$ref": "#/components/schemas/Assertion" + }, + "that": { + "$ref": "#/components/schemas/Assertion" + }, + "which": { + "$ref": "#/components/schemas/Assertion" + }, + "and": { + "$ref": "#/components/schemas/Assertion" + }, + "has": { + "$ref": "#/components/schemas/Assertion" + }, + "have": { + "$ref": "#/components/schemas/Assertion" + }, + "with": { + "$ref": "#/components/schemas/Assertion" + }, + "at": { + "$ref": "#/components/schemas/Assertion" + }, + "of": { + "$ref": "#/components/schemas/Assertion" + }, + "same": { + "$ref": "#/components/schemas/Assertion" + }, + "but": { + "$ref": "#/components/schemas/Assertion" + }, + "does": { + "$ref": "#/components/schemas/Assertion" + }, + "above": { + "$ref": "#/components/schemas/NumberComparer" + }, + "gt": { + "$ref": "#/components/schemas/NumberComparer" + }, + "greaterThan": { + "$ref": "#/components/schemas/NumberComparer" + }, + "least": { + "$ref": "#/components/schemas/NumberComparer" + }, + "gte": { + "$ref": "#/components/schemas/NumberComparer" + }, + "greaterThanOrEqual": { + "$ref": "#/components/schemas/NumberComparer" + }, + "below": { + "$ref": "#/components/schemas/NumberComparer" + }, + "lt": { + "$ref": "#/components/schemas/NumberComparer" + }, + "lessThan": { + "$ref": "#/components/schemas/NumberComparer" + }, + "most": { + "$ref": "#/components/schemas/NumberComparer" + }, + "lte": { + "$ref": "#/components/schemas/NumberComparer" + }, + "lessThanOrEqual": { + "$ref": "#/components/schemas/NumberComparer" + }, + "instanceof": { + "$ref": "#/components/schemas/InstanceOf" + }, + "instanceOf": { + "$ref": "#/components/schemas/InstanceOf" + }, + "not": { + "$ref": "#/components/schemas/Assertion" + }, + "deep": { + "$ref": "#/components/schemas/Deep" + }, + "ordered": { + "$ref": "#/components/schemas/Ordered" + }, + "nested": { + "$ref": "#/components/schemas/Nested" + }, + "own": { + "$ref": "#/components/schemas/Own" + }, + "any": { + "$ref": "#/components/schemas/KeyFilter" + }, + "all": { + "$ref": "#/components/schemas/KeyFilter" + }, + "a": { + "$ref": "#/components/schemas/Assertion" + }, + "an": { + "$ref": "#/components/schemas/Assertion" + }, + "include": { + "$ref": "#/components/schemas/Include" + }, + "includes": { + "$ref": "#/components/schemas/Include" + }, + "contain": { + "$ref": "#/components/schemas/Include" + }, + "contains": { + "$ref": "#/components/schemas/Include" + }, + "ok": { + "$ref": "#/components/schemas/Assertion" + }, + "true": { + "$ref": "#/components/schemas/Assertion" + }, + "false": { + "$ref": "#/components/schemas/Assertion" + }, + "null": { + "$ref": "#/components/schemas/Assertion" + }, + "undefined": { + "$ref": "#/components/schemas/Assertion" + }, + "NaN": { + "$ref": "#/components/schemas/Assertion" + }, + "exist": { + "$ref": "#/components/schemas/Assertion" + }, + "empty": { + "$ref": "#/components/schemas/Assertion" + }, + "arguments": { + "$ref": "#/components/schemas/Assertion" + }, + "Arguments": { + "$ref": "#/components/schemas/Assertion" + }, + "finite": { + "$ref": "#/components/schemas/Assertion" + }, + "equal": { + "$ref": "#/components/schemas/Equal" + }, + "equals": { + "$ref": "#/components/schemas/Equal" + }, + "eq": { + "$ref": "#/components/schemas/Equal" + }, + "eql": { + "$ref": "#/components/schemas/Equal" + }, + "eqls": { + "$ref": "#/components/schemas/Equal" + }, + "property": { + "$ref": "#/components/schemas/Property" + }, + "ownProperty": { + "$ref": "#/components/schemas/Property" + }, + "haveOwnProperty": { + "$ref": "#/components/schemas/Property" + }, + "ownPropertyDescriptor": { + "$ref": "#/components/schemas/OwnPropertyDescriptor" + }, + "haveOwnPropertyDescriptor": { + "$ref": "#/components/schemas/OwnPropertyDescriptor" + }, + "length": { + "$ref": "#/components/schemas/Length" + }, + "lengthOf": { + "$ref": "#/components/schemas/Length" + }, + "match": { + "$ref": "#/components/schemas/Match" + }, + "matches": { + "$ref": "#/components/schemas/Match" + }, + "keys": { + "$ref": "#/components/schemas/Keys" + }, + "throw": { + "$ref": "#/components/schemas/Throw" + }, + "throws": { + "$ref": "#/components/schemas/Throw" + }, + "Throw": { + "$ref": "#/components/schemas/Throw" + }, + "respondTo": { + "$ref": "#/components/schemas/RespondTo" + }, + "respondsTo": { + "$ref": "#/components/schemas/RespondTo" + }, + "itself": { + "$ref": "#/components/schemas/Assertion" + }, + "satisfy": { + "$ref": "#/components/schemas/Satisfy" + }, + "satisfies": { + "$ref": "#/components/schemas/Satisfy" + }, + "closeTo": { + "$ref": "#/components/schemas/CloseTo" + }, + "approximately": { + "$ref": "#/components/schemas/CloseTo" + }, + "members": { + "$ref": "#/components/schemas/Members" + }, + "increase": { + "$ref": "#/components/schemas/PropertyChange" + }, + "increases": { + "$ref": "#/components/schemas/PropertyChange" + }, + "decrease": { + "$ref": "#/components/schemas/PropertyChange" + }, + "decreases": { + "$ref": "#/components/schemas/PropertyChange" + }, + "change": { + "$ref": "#/components/schemas/PropertyChange" + }, + "changes": { + "$ref": "#/components/schemas/PropertyChange" + }, + "extensible": { + "$ref": "#/components/schemas/Assertion" + }, + "sealed": { + "$ref": "#/components/schemas/Assertion" + }, + "frozen": { + "$ref": "#/components/schemas/Assertion" + }, + "oneOf": { + "$ref": "#/components/schemas/OneOf" + } + }, + "required": [ + "to", + "be", + "been", + "is", + "that", + "which", + "and", + "has", + "have", + "with", + "at", + "of", + "same", + "but", + "does", + "above", + "gt", + "greaterThan", + "least", + "gte", + "greaterThanOrEqual", + "below", + "lt", + "lessThan", + "most", + "lte", + "lessThanOrEqual", + "instanceof", + "instanceOf", + "not", + "deep", + "ordered", + "nested", + "own", + "any", + "all", + "a", + "an", + "include", + "includes", + "contain", + "contains", + "ok", + "true", + "false", + "null", + "undefined", + "NaN", + "exist", + "empty", + "arguments", + "Arguments", + "finite", + "equal", + "equals", + "eq", + "eql", + "eqls", + "property", + "ownProperty", + "haveOwnProperty", + "ownPropertyDescriptor", + "haveOwnPropertyDescriptor", + "length", + "lengthOf", + "match", + "matches", + "keys", + "throw", + "throws", + "Throw", + "respondTo", + "respondsTo", + "itself", + "satisfy", + "satisfies", + "closeTo", + "approximately", + "members", + "increase", + "increases", + "decrease", + "decreases", + "change", + "changes", + "extensible", + "sealed", + "frozen", + "oneOf" + ], + "type": "object", + "additionalProperties": false + }, + "Object": { + "description": "Provides functionality common to all JavaScript objects.", + "properties": { + "should": { + "$ref": "#/components/schemas/Chai.Assertion" + } + }, + "required": ["should"], + "type": "object", + "additionalProperties": false + }, + "ValidateErrorJSON": { + "properties": { + "message": { + "type": "string", + "enum": ["Validation failed"], + "nullable": false + }, + "details": { + "properties": {}, + "additionalProperties": {}, + "type": "object" + } + }, + "required": ["message", "details"], + "type": "object", + "additionalProperties": false + }, + "IUser": { + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "address": { + "type": "string" + }, + "password": { + "type": "string" + }, + "authorities": { + "items": { + "type": "string" + }, + "type": "array" + }, + "restrictions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "roles": { + "items": { + "type": "string" + }, + "type": "array" + }, + "active": { + "type": "boolean" + }, + "activationKey": { + "type": "string" + }, + "accessRestricted": { + "type": "boolean" + }, + "githubOauthAccessToken": { + "type": "string" + }, + "resetKey": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "deleted": { + "type": "boolean" + }, + "deletedBy": { + "type": "string" + }, + "deletedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "string" + }, + "updatedBy": { + "type": "string" + } + }, + "required": [ + "name", + "email", + "authorities", + "restrictions", + "roles", + "active", + "accessRestricted", + "createdAt", + "updatedAt", + "deleted" + ], + "type": "object", + "additionalProperties": false + } + }, + "securitySchemes": {} + }, + "info": { + "title": "student-workflow-api", + "version": "1.0.0", + "license": { + "name": "ISC" + }, + "contact": { + "name": "NFS-Team" + } + }, + "openapi": "3.0.0", + "paths": { + "/users/{userId}": { + "post": { + "operationId": "GetUser", + "responses": { + "200": { + "description": "Ok", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Object" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidateErrorJSON" + } + } + } + } + }, + "description": "Retrieves the details of an existing user.\r\nSupply the unique user ID from either and receive corresponding user details.", + "security": [], + "parameters": [ + { + "in": "path", + "name": "userId", + "required": true, + "schema": { + "format": "double", + "type": "number" + } + }, + { + "in": "query", + "name": "name", + "required": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IUser" + } + } + } + } + } + } + }, + "servers": [ + { + "url": "/" + } + ] +} diff --git a/backend-app/swagger.yaml b/backend-app/swagger.yaml deleted file mode 100644 index 228461c..0000000 --- a/backend-app/swagger.yaml +++ /dev/null @@ -1,35 +0,0 @@ -openapi: 3.0.0 -info: - title: API Documentation - description: Student workflow organizer API Documentation with swagger. - version: 1.0 - contact: - email: contact@gmail.com - license: - name: MIT License - url: 'https://opensource.org/licenses/MIT' -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - security: - - bearerAuth: [] - responses: - '200': - description: OK - content: - application/json: {} - '201': - description: CREATED - content: - application/json: {} - '404': - description: NOT FOUND - '400': - description: BAD REQUEST - '401': - description: UNAUTHORIZED - '403': - description: FORBIDDEN diff --git a/backend-app/tests/db_config.js b/backend-app/tests/db_config.js deleted file mode 100644 index 9836623..0000000 --- a/backend-app/tests/db_config.js +++ /dev/null @@ -1,21 +0,0 @@ -const mongoose = require('mongoose'); -require('dotenv').config(); - -beforeAll(() => { - // check if db isn't already connected - if (mongoose.connection.readyState === 0) { - mongoose.set('strictQuery', false); - mongoose.connect(process.env.MONGO_URI_TEST, { - useNewUrlParser: true, - useUnifiedTopology: true, - }); - } - // const res = await request(app).post('/api/auth/signup').send({ - // name: testUserCredentials.userName, - // email: testUserCredentials.userEmail, - // password: testUserCredentials.userPassword, - // }); -}); -afterAll(async () => { - await mongoose.disconnect(); -}); diff --git a/backend-app/tests/db_config.spec.ts b/backend-app/tests/db_config.spec.ts new file mode 100644 index 0000000..756d18a --- /dev/null +++ b/backend-app/tests/db_config.spec.ts @@ -0,0 +1,26 @@ +const mongoose = require('mongoose'); +const expect = require('chai').expect; +import '@config/app_config'; +import createDefaultUser from '@utils/create_default_user'; +import createRoles from '@utils/authorization/roles/create_roles'; +// import logger from '@root/utils/logger'; + +before(async () => { + mongoose.set('strictQuery', false); + await mongoose.connect(process.env.MONGO_URI_TEST, { + useNewUrlParser: true, + useUnifiedTopology: true, + }); + await createRoles(); + await createDefaultUser(); +}); +after(async () => { + await mongoose.connection.dropDatabase(); + await mongoose.connection.close(); +}); + +describe('Database connection', () => { + it('should connect to the database', () => { + expect(mongoose.connection.readyState).to.equal(1); + }); +}); diff --git a/backend-app/tests/e2e/auth/auth.spec.ts b/backend-app/tests/e2e/auth/auth.spec.ts new file mode 100644 index 0000000..4795396 --- /dev/null +++ b/backend-app/tests/e2e/auth/auth.spec.ts @@ -0,0 +1,460 @@ +import chai from 'chai'; +import { describe, it } from 'mocha'; +import mongoose from 'mongoose'; +import app from '@root/app'; +import User from '@models/user/user_model'; +import AuthUtils from '@utils/authorization/auth_utils'; +import * as supertest from 'supertest'; +const { generateAccessToken } = AuthUtils; +const agent = supertest.agent(app); +const expect = chai.expect; +import request from 'supertest'; + +let res: request.Response; + +describe('Auth API', () => { + describe('POST /signup', () => { + it('should return an error if email is not provided', async () => { + res = await agent.post('/api/auth/signup').send({ + name: 'Test User', + password: 'password123', + }); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'User validation failed: email: Please fill your email' + ); + }); + + it('should return an error if email is invalid', async () => { + res = await agent.post('/api/auth/signup').send({ + name: 'Test User', + email: 'invalidemail', + password: 'password123', + }); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'User validation failed: email: Please provide a valid email' + ); + }); + + it('should return an error if password is not provided', async () => { + res = await agent.post('/api/auth/signup').send({ + name: 'Test User', + email: 'testuser@example.com', + }); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'Please provide a password' + ); + }); + + it('should create a new user', async () => { + res = await agent.post('/api/auth/signup').send({ + name: 'Test User', + email: 'testuser@example.com', + password: 'password123', + }); + + expect(res.status).to.equal(201); + expect(res.body).to.have.property('accessToken'); + expect(res.body).to.have.property('user'); + expect(res.body.user).to.have.property('name', 'Test User'); + expect(res.body.user).to.have.property( + 'email', + 'testuser@example.com' + ); + expect(res.body.user).to.not.have.property('password'); + expect(res.body.user).to.not.have.property('activationKey'); + }); + }); + + afterEach(function () { + const errorBody = res && res.body; + if (this.currentTest.state === 'failed' && errorBody) { + console.debug('res: ', errorBody); + } + + res = null; + }); + describe('POST /login', () => { + it('should login a user', async () => { + res = await agent.post('/api/auth/login').send({ + email: 'testuser@example.com', + password: 'password123', + }); + + expect(res.status).to.equal(200); + expect(res.body).to.have.property('accessToken'); + expect(res.body).to.have.property('user'); + expect(res.body.user).to.have.property('name', 'Test User'); + expect(res.body.user).to.have.property( + 'email', + 'testuser@example.com' + ); + expect(res.body.user).to.not.have.property('password'); + expect(res.body.user).to.not.have.property('activationKey'); + }); + + it('should return an error if email is not provided', async () => { + res = await agent.post('/api/auth/login').send({ + password: 'password123', + }); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'Invalid email or password' + ); + }); + + it('should return an error if email is invalid', async () => { + res = await agent.post('/api/auth/login').send({ + email: 'invalidemail', + password: 'password123', + }); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'Invalid email or password' + ); + }); + + it('should return an error if password is not provided', async () => { + res = await agent.post('/api/auth/login').send({ + email: 'testuser@example.com', + }); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'Please provide a password' + ); + }); + + it('should return an error if email or password is incorrect', async () => { + res = await agent.post('/api/auth/login').send({ + email: 'testuser@example.com', + password: 'wrongpassword', + }); + + expect(res.status).to.equal(401); + expect(res.body).to.have.property( + 'message', + 'Email or Password is wrong' + ); + }); + }); + + describe('GET /activate', () => { + let user: any; + + // login user each time + beforeEach(async () => { + user = await User.findOne({ email: 'testuser@example.com' }).select( + '+activationKey' + ); + }); + + it('should return an error if activation key is not provided', async () => { + res = await agent.get( + `/api/auth/activate?id=${user._id.toString()}` + ); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'Please provide activation key' + ); + }); + + it('should return an error if user id is not provided', async () => { + res = await agent.get( + `/api/auth/activate?activationKey=${user.activationKey}` + ); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'Please provide user id' + ); + }); + + it('should return an error if user id is invalid', async () => { + res = await agent.get( + `/api/auth/activate?id=invalidid&activationKey=${user.activationKey}` + ); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'Please provide a valid user id' + ); + }); + + it('should return an error if activation key is invalid', async () => { + res = await agent.get( + `/api/auth/activate?id=${user._id.toString()}&activationKey=invalidkey` + ); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'Invalid activation key' + ); + }); + + it('should return an error if user does not exist', async () => { + res = await agent.get( + `/api/auth/activate?id=${new mongoose.Types.ObjectId()}&activationKey=${ + user.activationKey + }` + ); + + expect(res.status).to.equal(404); + expect(res.body).to.have.property('message', 'User does not exist'); + }); + + it('should activate a user account', async () => { + res = await agent.get( + `/api/auth/activate?id=${user._id.toString()}&activationKey=${ + user.activationKey + }` + ); + + expect(res.status).to.equal(200); + expect(res.body).to.have.property('user'); + expect(res.body.user).to.have.property('name', 'Test User'); + expect(res.body.user).to.have.property( + 'email', + 'testuser@example.com' + ); + expect(res.body.user).to.not.have.property('password'); + expect(res.body.user).to.not.have.property('activationKey'); + expect(res.body.user).to.have.property('active', true); + }); + it('should return an error if user is already active', async () => { + res = await agent.get( + `/api/auth/activate?id=${user._id.toString()}&activationKey=${ + user.activationKey + }` + ); + + expect(res.status).to.equal(409); + expect(res.body).to.have.property( + 'message', + 'User is already active' + ); + }); + }); + + describe(' GET /auth/refreshToken', () => { + let accessToken: string; + let refreshToken: string; + + // login user each time + beforeEach(async () => { + const user = await User.findOne({ email: 'testuser@example.com' }); + accessToken = AuthUtils.generateAccessToken(user._id.toString()); + refreshToken = AuthUtils.generateRefreshToken(user._id.toString()); + }); + + it('should return an error if refresh token is invalid', async () => { + res = await agent + .get('/api/auth/refreshToken') + .set('Cookie', `access_token=${accessToken}`) + .set('Cookie', `refresh_token=invalidtoken; HttpOnly`); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'Invalid refresh token' + ); + }); + + it('should return an error if refresh token is not provided', async () => { + res = await agent + .get('/api/auth/refreshToken') + .set('Cookie', `access_token=${accessToken}`); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'You have to login to continue.' + ); + }); + + it('should refresh access token', async () => { + // refresh token and access token to be sent in cookies + res = await agent + .get('/api/auth/refreshToken') + .set('Cookie', `access_token=${accessToken}`) + .set('Cookie', `refresh_token=${refreshToken}; HttpOnly`); + + expect(res.status).to.equal(204); + expect(res.header['set-cookie']).to.not.include('access_token'); + }); + }); + + describe('POST /auth/logout', () => { + it('should logout a user', async () => { + const user = await User.findOne({ email: 'testuser@example.com' }); + const accessToken = generateAccessToken(user._id.toString()); + + res = await agent + .delete('/api/auth/logout') + .set('Cookie', `access_token=${accessToken}`); + + expect(res.status).to.equal(204); + const setCookieHeader = res.headers['set-cookie']; + if (setCookieHeader) { + const cookies = setCookieHeader.map( + (cookie: string) => cookie.split(';')[0] + ); + expect(cookies).to.not.include('access_token'); + expect(cookies).to.not.include('refresh_token'); + } + }); + + it('should return an error if access token is not provided', async () => { + res = await agent.delete('/api/auth/logout'); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'Please provide access token' + ); + }); + }); + + // delete user after all tests + // after(async () => { + // await User.deleteMany({ email: 'testuser@example.com' }); + // }); +}); +describe('User API', () => { + let user: any; + let accessToken: string; + beforeEach(async () => { + res = await agent.post('/api/auth/login').send({ + email: 'testuser@example.com', + password: 'password123', + }); + + user = res.body.user; + accessToken = res.body.accessToken; + }); + afterEach(function () { + const errorBody = res && res.body; + if (this.currentTest.state === 'failed' && errorBody) { + console.debug('res: ', errorBody); + } + + res = null; + }); + + describe('GET /api/users/me', () => { + it('should return the current user', async () => { + res = await agent + .get('/api/users/me') + .set('Cookie', `access_token=${accessToken}`); + + expect(res.status).to.equal(200); + expect(res.body).to.have.property('user'); + expect(res.body.user).to.have.property( + '_id', + user._id.toString().toString() + ); + expect(res.body.user).to.have.property('name', user.name); + expect(res.body.user).to.have.property('email', user.email); + }); + }); + + describe('PATCH /api/users/me', () => { + it('should return an error if the user tries to update their password', async () => { + res = await agent + .patch('/api/users/me') + .set('Cookie', `access_token=${accessToken}`) + .send({ + password: 'newpassword123', + passwordConfirm: 'newpassword123', + }); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'This route is not for password updates. Please use /updateMyPassword' + ); + }); + + it('should return an error if the user tries to update their role', async () => { + res = await agent + .patch('/api/users/me') + .set('Cookie', `access_token=${accessToken}`) + .send({ + roles: ['admin'], + }); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'This route is not for role updates. Please use /updateRole' + ); + }); + + it('should return an error if the user provides invalid data', async () => { + res = await agent + .patch('/api/users/me') + .set('Cookie', `access_token=${accessToken}`) + .send({ + email: 'invalidemail', + }); + + expect(res.status).to.equal(400); + expect(res.body).to.have.property( + 'message', + 'Validation failed: email: Please provide a valid email' + ); + }); + + it('should update the current user', async () => { + res = await agent + .patch('/api/users/me') + .set('Cookie', `access_token=${accessToken}`) + .send({ + name: 'Updated Name', + }); + + expect(res.status).to.equal(200); + expect(res.body).to.have.property('doc'); + expect(res.body.doc).to.have.property( + '_id', + user._id.toString().toString() + ); + expect(res.body.doc).to.have.property('name', 'Updated Name'); + + // Check if the user was updated in the database + const updatedUser = await User.findById(user._id.toString()); + expect(updatedUser).to.have.property('name', 'Updated Name'); + }); + }); + describe('DELETE /api/users/me', () => { + it('should delete the current user', async () => { + res = await agent + .delete('/api/users/me') + .set('Cookie', `access_token=${accessToken}`); + + expect(res.status).to.equal(204); + + // Check if the user was deleted from the database + const deletedUser = await User.findById(user._id.toString()); + expect(deletedUser).to.not.exist; + }); + }); +}); diff --git a/backend-app/tests/e2e/auth/login_signup.test.js b/backend-app/tests/e2e/auth/login_signup.test.js deleted file mode 100644 index b960b28..0000000 --- a/backend-app/tests/e2e/auth/login_signup.test.js +++ /dev/null @@ -1,88 +0,0 @@ -const request = require('supertest'); -const app = require('../../../app'); -const { testUserCredentials } = require('../../testConstants'); -const { createUser, deleteUser } = require('../../utils'); -const { REQUIRE_ACTIVATION } = require('../../../config/app_config'); - -describe('POST /api/auth/login', () => { - // console.log('db connected: ', mongoose.connection.readyState); - - beforeAll(async () => { - await createUser( - app, - testUserCredentials.userName, - testUserCredentials.userEmail, - testUserCredentials.userPassword - ); - }); - - it('should return a JWT token on successful login', async () => { - const response = await request(app) - .post('/api/auth/login') - .send({ - email: testUserCredentials.userEmail, - password: testUserCredentials.userPassword, - }) - .expect(200); - expect(response.body.accessToken).toBeDefined(); - }); - - it('should return 401 if invalid credentials are provided', async () => { - await request(app) - .post('/api/auth/login') - .send({ - email: 'random@gmail.com', - password: 'admin123424', - }) - .expect(401); - }); - afterAll(async () => { - await deleteUser( - app, - testUserCredentials.userEmail, - testUserCredentials.userPassword - ); - }); -}); - -describe('POST /api/auth/signup', () => { - beforeAll(async () => { - await deleteUser( - app, - testUserCredentials.userEmail, - testUserCredentials.userPassword - ); - }); - - // it('should create a new user', async () => { - // const response = await createUser( - // app, - // testUserCredentials.userName, - // testUserCredentials.userEmail, - // testUserCredentials.userPassword - // ); - // expect(response.status).toBe(201); - // expect(response.body.user).toBeDefined(); - // expect(response.body.user.name).toBe(testUserCredentials.userName); - // expect(response.body.user.email).toBe(testUserCredentials.userEmail); - // expect(response.body.user.roles).toEqual( - // expect.arrayContaining(['USER']) - // ); - // expect(response.body.accessToken).toBeDefined(); - // expect(response.body.user.active).toBe(!REQUIRE_ACTIVATION); - // token = response.body.token; - // userId = response.body.user._id; - // }); - - afterAll(async () => { - await deleteUser( - app, - testUserCredentials.userEmail, - testUserCredentials.userPassword - ); - }); - - it('should return 400 if required fields are missing', async () => { - await request(app).post('/api/auth/signup').send({}).expect(400); - }); -}); diff --git a/backend-app/tests/e2e/auth/user.test.js b/backend-app/tests/e2e/auth/user.test.js deleted file mode 100644 index 4b85df6..0000000 --- a/backend-app/tests/e2e/auth/user.test.js +++ /dev/null @@ -1,161 +0,0 @@ -const request = require('supertest'); -const app = require('../../../app'); -const { testUserCredentials } = require('../../testConstants'); -const { createUser, loginUser, deleteUser } = require('../../utils'); -const { REQUIRE_ACTIVATION } = require('../../../config/app_config'); -describe('PATCH /api/users/me', () => { - // if user is not logged in - // console.log('db connected: ', mongoose.connection.readyState); - let accessToken; - beforeAll(async () => { - await createUser( - app, - testUserCredentials.userName, - testUserCredentials.userEmail, - testUserCredentials.userPassword - ); - const res = await loginUser( - app, - testUserCredentials.userEmail, - testUserCredentials.userPassword - ); - accessToken = res.body.accessToken; - }); - it('should return 401 if user is not logged in', async () => { - const res = await request(app) - .patch('/api/users/me') - .send({ - name: 'John Doe', - email: 'abdo@gmail.com', - }) - .expect(401); - }); - // if user is logged in - it('should update the user if user is logged in', async () => { - await request(app) - .patch('/api/users/me') - .set('Authorization', `Bearer ${accessToken}`) - .send({ - name: 'John Doe', - }) - .expect(200); - }); - // if user tries to update password - it('should return 400 if user tries to update password', async () => { - await request(app) - .patch('/api/users/me') - .set('Authorization', `Bearer ${accessToken}`) - .send({ - password: '123456789', - }) - .expect(400); - }); - // if user tries to update roles - it('should return 400 if user tries to update roles', async () => { - await request(app) - .patch('/api/users/me') - .set('Authorization', `Bearer ${accessToken}`) - .send({ - roles: ['ADMIN'], - }) - .expect(400); - }); - afterAll(async () => { - await deleteUser( - app, - testUserCredentials.userEmail, - testUserCredentials.userPassword - ); - }); -}); -describe('DELETE /api/users/me', () => { - let accessToken; - beforeAll(async () => { - await createUser( - app, - testUserCredentials.userName, - testUserCredentials.userEmail, - testUserCredentials.userPassword - ); - const res = await loginUser( - app, - testUserCredentials.userEmail, - testUserCredentials.userPassword - ); - accessToken = res.body.accessToken; - }); - it('should delete the user if user is logged in', async () => { - await request(app) - .delete('/api/users/me') - .set('Authorization', `Bearer ${accessToken}`) - .expect(204); - }); - afterAll(async () => { - await deleteUser( - app, - testUserCredentials.userEmail, - testUserCredentials.userPassword - ); - }); -}); - -if (REQUIRE_ACTIVATION) - describe('Account Activation : GET /api/auth/activate', () => { - let user; - let activationKey; - beforeAll(async () => { - user = await user_model - .findOne({ email: testUserCredentials.userEmail }) - .select('+activationKey'); - activationKey = user.activationKey; - }); - it('should return 400 if activation key is missing', async () => { - await request(app).get('/api/auth/activate').query({}).expect(400); - }); - it('should return 400 if id is missing', async () => { - await request(app) - .get('/api/auth/activate') - .query({ activationKey: activationKey }) - .expect(400); - }); - it('should return 400 if id is invalid', async () => { - await request(app) - .get('/api/auth/activate') - .query({ activationKey: activationKey, id: 'invalid_id' }) - .expect(400); - }); - // if user not found - it('should return 404 if user is not found', async () => { - await request(app) - .get('/api/auth/activate') - .query({ - activationKey: activationKey, - id: '5f9b3b3b3b3b3b3b3b3b3b3b', - }) - .expect(404); - }); - it('should return 400 if activation key is invalid', async () => { - await request(app) - .get('/api/auth/activate') - .query({ activationKey: 'invalid_key', id: userId }) - .expect(400); - }); - it('should return 200 if activation key is valid', async () => { - await request(app) - .get('/api/auth/activate') - .query({ activationKey: activationKey, id: userId }) - .expect(200); - }); - it('should return 409 if user is already activated', async () => { - await request(app) - .get('/api/auth/activate') - .query({ activationKey: activationKey, id: userId }) - .expect(409); - }); - }); -else - describe('GET /api/auth/activate', () => { - it('should return 404', async () => { - await request(app).get('/api/auth/activate'); - }); - }); diff --git a/backend-app/tests/env.test.ts b/backend-app/tests/env.test.ts new file mode 100644 index 0000000..f7534b3 --- /dev/null +++ b/backend-app/tests/env.test.ts @@ -0,0 +1 @@ +process.env.NODE_ENV = 'test'; diff --git a/backend-app/tests/init/x.spec.ts b/backend-app/tests/init/x.spec.ts new file mode 100644 index 0000000..b67fe01 --- /dev/null +++ b/backend-app/tests/init/x.spec.ts @@ -0,0 +1,7 @@ +import { describe, it } from 'mocha'; + +describe('Your test suite', () => { + it('Your test case', () => { + // Your test assertion goes here + }); +}); diff --git a/backend-app/tests/init/roles.test.js b/backend-app/tests/roles.spec.ts similarity index 64% rename from backend-app/tests/init/roles.test.js rename to backend-app/tests/roles.spec.ts index fb874cc..d3bc576 100644 --- a/backend-app/tests/init/roles.test.js +++ b/backend-app/tests/roles.spec.ts @@ -1,8 +1,15 @@ +// imprt expect from chai + +import '../utils/register_paths'; + +import expect from 'expect'; + describe('Role tests', () => { - test('should create roles', async () => { + it('should create roles', () => { // await createRoles(); // const response = await request(app).post('/ap/auth/signup'); // console.log(response.body); + expect(1).toBe(1); }); it('should create default user', async () => { // await createDefaultUser(); diff --git a/backend-app/tests/setup.js b/backend-app/tests/setup.js deleted file mode 100644 index 9c02606..0000000 --- a/backend-app/tests/setup.js +++ /dev/null @@ -1,19 +0,0 @@ -const request = require('supertest'); -const createRoles = require('../utils/authorization/role/create_roles'); -const createDefaultUser = require('../utils/create_default_user'); -const { testUserCredentials } = require('./testConstants'); -const { MONGO_URI_TEST } = require('../config/app_config'); -const app = require('../app'); -const mongoose = require('mongoose'); - -async function globalSetup() { - mongoose.set('strictQuery', false); - mongoose.connect(MONGO_URI_TEST, { - useNewUrlParser: true, - useUnifiedTopology: true, - }); - await createRoles(); - await createDefaultUser(); -} - -module.exports = globalSetup; diff --git a/backend-app/tests/teardown.js b/backend-app/tests/teardown.js deleted file mode 100644 index 3ed52d8..0000000 --- a/backend-app/tests/teardown.js +++ /dev/null @@ -1,7 +0,0 @@ -const mongoose = require('mongoose'); -async function globalTeardown() { - await mongoose.connection.dropDatabase(); - await mongoose.disconnect(); -} - -module.exports = globalTeardown; diff --git a/backend-app/tests/testConstants.js b/backend-app/tests/testConstants.js deleted file mode 100644 index 6578fc4..0000000 --- a/backend-app/tests/testConstants.js +++ /dev/null @@ -1,5 +0,0 @@ -exports.testUserCredentials = { - userEmail: 'user@gmail.com', - userPassword: 'user123', - userName: 'John Doe', -}; diff --git a/backend-app/tests/utils.js b/backend-app/tests/utils.js deleted file mode 100644 index 5f5e720..0000000 --- a/backend-app/tests/utils.js +++ /dev/null @@ -1,35 +0,0 @@ -const request = require('supertest'); - -createUser = async (app, name, email, password) => { - const res = await request(app).post('/api/auth/signup').send({ - name, - email, - password, - }); - return res; -}; - -loginUser = async (app, email, password) => { - const res = await request(app).post('/api/auth/login').send({ - email, - password, - }); - return res; -}; - -deleteUser = async (app, email, password) => { - // login user - const res = await loginUser(app, email, password); - const accessToken = res.body.accessToken; - // delete user - const res2 = await request(app) - .delete('/api/users/me') - .set('Authorization', `Bearer ${accessToken}`); - - return res2; -}; -module.exports = { - createUser, - loginUser, - deleteUser, -}; diff --git a/backend-app/tsconfig.json b/backend-app/tsconfig.json index db5e794..73aa2f5 100644 --- a/backend-app/tsconfig.json +++ b/backend-app/tsconfig.json @@ -1,28 +1,43 @@ { "compilerOptions": { + "target": "es6", "module": "commonjs", + "outDir": "build", + "baseUrl": ".", "esModuleInterop": true, - "target": "es6", + "forceConsistentCasingInFileNames": true, + "noImplicitAny": true, + "noImplicitThis": true, + "alwaysStrict": true, + + "noUnusedLocals": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + "moduleResolution": "node", + "resolveJsonModule": true, + + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "sourceMap": true, - "outDir": "dist", "allowJs": true, - "strictNullChecks": true, "allowUnreachableCode": false, - "noUnusedLocals": true, - "strictFunctionTypes": true, - "noImplicitReturns": true, - "noUncheckedIndexedAccess": true, - "baseUrl": "./", + "paths": { + "@root/*": ["./*"], + "@config/*": ["./config/*"], "@utils/*": ["./utils/*"], "@models/*": ["./models/*"], "@controllers/*": ["./controllers/*"], "@middlewares/*": ["./middlewares/*"], - "@constants/*": ["./constants/*"] - } + "@constants/*": ["./constants/*"], + "@interfaces/*": ["./interfaces/*"] + }, + "typeRoots": ["./typings"] }, - "include": ["**/*.ts", "**/*.js"], - "exclude": ["node_modules", "**/*.spec.ts"] + "include": ["./**/*"], + "exclude": ["node_modules", "build"] } diff --git a/backend-app/tsoa.json b/backend-app/tsoa.json new file mode 100644 index 0000000..1ce4849 --- /dev/null +++ b/backend-app/tsoa.json @@ -0,0 +1,12 @@ +{ + "entryFile": "./server.ts", + "noImplicitAdditionalProperties": "throw-on-extras", + "controllerPathGlobs": ["./controllers/**/*.ts"], + "spec": { + "outputDirectory": "./", + "specVersion": 3 + }, + "routes": { + "routesDir": "build" + } +} diff --git a/backend-app/typings/express-serve-static-core.d.ts b/backend-app/typings/express-serve-static-core.d.ts new file mode 100644 index 0000000..d24c981 --- /dev/null +++ b/backend-app/typings/express-serve-static-core.d.ts @@ -0,0 +1,18 @@ +import { Express } from 'express-serve-static-core'; +import { ObjectId } from 'mongoose'; +declare module 'express-serve-static-core' { + interface Request { + user: + | { + _id: ObjectId; + name?: string; + email: string; + roles?: string[]; + authorities?: string[]; + restrictions?: string[]; + active: boolean; + githubOauthAccessToken?: string; + } + | undefined; + } +} diff --git a/backend-app/typings/xss-clean.d.ts b/backend-app/typings/xss-clean.d.ts new file mode 100644 index 0000000..de13de3 --- /dev/null +++ b/backend-app/typings/xss-clean.d.ts @@ -0,0 +1,5 @@ +declare module 'xss-clean' { + const value: Function; + + export default value; +} diff --git a/backend-app/utils/api_features.js b/backend-app/utils/api_features.js deleted file mode 100644 index c45dcb2..0000000 --- a/backend-app/utils/api_features.js +++ /dev/null @@ -1,34 +0,0 @@ -class APIFeatures { - constructor(query, queryString) { - this.query = query; - this.queryString = queryString; - } - - sort() { - if (this.queryString.sort) { - const sortBy = this.queryString.sort.split(',').join(' '); - this.query = this.query.sort(sortBy); - } - return this; - } - - paginate() { - const page = this.queryString.page * 1 || 1; - const limit = this.queryString.limit * 1 || 10; - const skip = (page - 1) * limit; - - this.query = this.query.skip(skip).limit(limit); - return this; - } - - // Field Limiting ex: -----/user?fields=name,email,address - limitFields() { - if (this.queryString.fields) { - const fields = this.queryString.fields.split(',').join(' '); - this.query = this.query.select(fields); - } - return this; - } -} - -module.exports = APIFeatures; diff --git a/backend-app/utils/api_features.ts b/backend-app/utils/api_features.ts new file mode 100644 index 0000000..d796b77 --- /dev/null +++ b/backend-app/utils/api_features.ts @@ -0,0 +1,45 @@ +import { Document, Query } from 'mongoose'; // Import appropriate types for your use case + +class APIFeatures { + query: Query; + queryString: Record; + constructor( + query: Query, + queryString: Record + ) { + this.query = query; + this.queryString = queryString; + } + + sort(): this { + if (this.queryString.sort) { + const sortBy = (this.queryString.sort as string) + .split(',') + .join(' '); + this.query = this.query.sort(sortBy); + } + return this; + } + + paginate(): this { + const page = Number(this.queryString.page) || 1; + const limit = Number(this.queryString.limit) || 10; + const skip = (page - 1) * limit; + + this.query = this.query.skip(skip).limit(limit); + return this; + } + + // Field Limiting ex: -----/user?fields=name,email,address + limitFields(): this { + if (this.queryString.fields) { + const fields = (this.queryString.fields as string) + .split(',') + .join(' '); + this.query = this.query.select(fields); + } + return this; + } +} + +export default APIFeatures; diff --git a/backend-app/utils/app_error.js b/backend-app/utils/app_error.js deleted file mode 100644 index 6d01701..0000000 --- a/backend-app/utils/app_error.js +++ /dev/null @@ -1,11 +0,0 @@ -class AppError extends Error { - constructor(statusCode, status, message, path = false) { - super(message); - this.statusCode = statusCode; - this.status = status; - this.message = message; - this.path = !path ? false : path; - } -} - -module.exports = AppError; diff --git a/backend-app/utils/app_error.ts b/backend-app/utils/app_error.ts new file mode 100644 index 0000000..b580181 --- /dev/null +++ b/backend-app/utils/app_error.ts @@ -0,0 +1,11 @@ +export default class AppError extends Error { + statusCode: Number; + status: string; + path: any; + constructor(statusCode: Number, message: string, path: any = false) { + super(message); + this.statusCode = statusCode; + this.message = message; + this.path = !path ? false : path; + } +} diff --git a/backend-app/utils/authorization/auth_utils.js b/backend-app/utils/authorization/auth_utils.js deleted file mode 100644 index 79b92b5..0000000 --- a/backend-app/utils/authorization/auth_utils.js +++ /dev/null @@ -1,57 +0,0 @@ -const { - ACCESS_TOKEN_SECRET, - ACCESS_TOKEN_EXPIRY_TIME, - REFRESH_TOKEN_SECRET, - REFRESH_TOKEN_EXPIRY_TIME, - ACCESS_TOKEN_COOKIE_EXPIRY_TIME, - REFRESH_TOKEN_COOKIE_EXPIRY_TIME, -} = require('../../config/app_config'); -const AppError = require('../app_error'); -const jwt = require('jsonwebtoken'); -const { promisify } = require('util'); - -class AuthUtils { - static generateAccessToken(id) { - return jwt.sign({ id }, ACCESS_TOKEN_SECRET, { - expiresIn: ACCESS_TOKEN_EXPIRY_TIME, - }); - } - static generateRefreshToken(id) { - return jwt.sign({ id }, REFRESH_TOKEN_SECRET, { - expiresIn: REFRESH_TOKEN_EXPIRY_TIME, - }); - } - static async verifyAccessToken(token) { - try { - return await promisify(jwt.verify)(token, ACCESS_TOKEN_SECRET); - } catch (error) { - throw new AppError(401, 'fail', 'Invalid token'); - } - } - static async verifyRefreshToken(token) { - try { - return await promisify(jwt.verify)(token, REFRESH_TOKEN_SECRET); - } catch (error) { - throw new AppError(401, 'fail', 'Invalid token'); - } - } - static setAccessTokenCookie(res, accessToken) { - res.cookie('access_token', accessToken, { - httpOnly: true, - secure: true, - sameSite: 'strict', - maxAge: ACCESS_TOKEN_COOKIE_EXPIRY_TIME, - }); - return this; - } - static setRefreshTokenCookie(res, refreshToken) { - res.cookie('refresh_token', refreshToken, { - httpOnly: true, - secure: true, - sameSite: 'strict', - maxAge: REFRESH_TOKEN_COOKIE_EXPIRY_TIME, - }); - return this; - } -} -module.exports = AuthUtils; diff --git a/backend-app/utils/authorization/auth_utils.ts b/backend-app/utils/authorization/auth_utils.ts new file mode 100644 index 0000000..27abaf0 --- /dev/null +++ b/backend-app/utils/authorization/auth_utils.ts @@ -0,0 +1,59 @@ +import { + ACCESS_TOKEN_SECRET, + ACCESS_TOKEN_EXPIRY_TIME, + REFRESH_TOKEN_SECRET, + REFRESH_TOKEN_EXPIRY_TIME, + ACCESS_TOKEN_COOKIE_EXPIRY_TIME, + REFRESH_TOKEN_COOKIE_EXPIRY_TIME, +} from '../../config/app_config'; +import AppError from '../app_error'; +import jwt from 'jsonwebtoken'; +import { promisify } from 'util'; + +class AuthUtils { + static generateAccessToken(_id: string): string { + return jwt.sign({ _id }, ACCESS_TOKEN_SECRET, { + expiresIn: ACCESS_TOKEN_EXPIRY_TIME, + }); + } + static generateRefreshToken(_id: string): string { + return jwt.sign({ _id }, REFRESH_TOKEN_SECRET, { + expiresIn: REFRESH_TOKEN_EXPIRY_TIME, + }); + } + static setAccessTokenCookie(res: any, accessToken: string): AuthUtils { + res.cookie('access_token', accessToken, { + secure: true, + sameSite: 'strict', + maxAge: ACCESS_TOKEN_COOKIE_EXPIRY_TIME, + }); + return this; + } + static setRefreshTokenCookie(res: any, refreshToken: string): AuthUtils { + res.cookie('refresh_token', refreshToken, { + httpOnly: true, + secure: true, + sameSite: 'strict', + maxAge: REFRESH_TOKEN_COOKIE_EXPIRY_TIME, + }); + return this; + } + static async verifyAccessToken(token: string): Promise { + const result = await promisify(jwt.verify.bind(jwt))( + token, + ACCESS_TOKEN_SECRET + ); + return result; + } + static async verifyRefreshToken(token: string): Promise { + try { + return await promisify(jwt.verify.bind(jwt))( + token, + REFRESH_TOKEN_SECRET + ); + } catch (error) { + throw new AppError(400, 'Invalid refresh token'); + } + } +} +export default AuthUtils; diff --git a/backend-app/utils/authorization/generateTokens.js b/backend-app/utils/authorization/generate_tokens.ts similarity index 57% rename from backend-app/utils/authorization/generateTokens.js rename to backend-app/utils/authorization/generate_tokens.ts index b0f18b7..d207e0a 100644 --- a/backend-app/utils/authorization/generateTokens.js +++ b/backend-app/utils/authorization/generate_tokens.ts @@ -1,17 +1,14 @@ -const { +import { ACCESS_TOKEN_SECRET, ACCESS_TOKEN_EXPIRY_TIME, REFRESH_TOKEN_SECRET, REFRESH_TOKEN_EXPIRY_TIME, -} = require('../../config/app_config'); -const AppError = require('../app_error'); -const TokenModel = require('../../models/token_model'); -const jwt = require('jsonwebtoken'); +} from '@config/app_config'; +import AppError from '../app_error'; +import jwt from 'jsonwebtoken'; -const generateTokens = async (id) => { +const generateTokens = (id: string) => { try { - const exists = await TokenModel.findOne({ userId: id }); - if (exists) await TokenModel.findByIdAndDelete(exists._id); const accessToken = jwt.sign({ id }, ACCESS_TOKEN_SECRET, { expiresIn: ACCESS_TOKEN_EXPIRY_TIME, }); @@ -21,21 +18,14 @@ const generateTokens = async (id) => { if (!accessToken || !refreshToken) throw new AppError( 500, - 'fail', 'Something went wrong. Please try again later.' ); - await TokenModel.create({ - accessToken, - refreshToken, - userId: id, - }); return { accessToken, refreshToken }; } catch (err) { throw new AppError( 500, - 'fail', 'Something went wrong. Please try again later.' ); } }; -module.exports = generateTokens; +export default generateTokens; diff --git a/backend-app/utils/authorization/github.js b/backend-app/utils/authorization/github.ts similarity index 55% rename from backend-app/utils/authorization/github.js rename to backend-app/utils/authorization/github.ts index 7c813bc..6df8099 100644 --- a/backend-app/utils/authorization/github.js +++ b/backend-app/utils/authorization/github.ts @@ -1,21 +1,21 @@ -const { - GITHUB_OAUTH_CLIENT_ID, - GITHUB_OAUTH_CLIENT_SECRET, -} = require('../../config/app_config'); -const qs = require('qs'); -const axios = require('axios'); -const AppError = require('../../utils/app_error'); +import { + OAUTH_CLIENT_ID_GITHUB, + OAUTH_CLIENT_SECRET_GITHUB, +} from '@config/app_config'; +import qs from 'qs'; +import axios from 'axios'; +import AppError from '@utils/app_error'; -exports.getGithubOAuthToken = async (code) => { +export const getGithubOAuthToken = async (code: string) => { const rootUrl = 'https://github.com/login/oauth/access_token'; const queryString = qs.stringify({ - client_id: GITHUB_OAUTH_CLIENT_ID, - client_secret: GITHUB_OAUTH_CLIENT_SECRET, + client_id: OAUTH_CLIENT_ID_GITHUB, + client_secret: OAUTH_CLIENT_SECRET_GITHUB, code, }); try { - const { data } = await axios.post(`${rootUrl}?${queryString}`, { + const { data } = await axios.post(`${rootUrl}?${queryString}`, null, { headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, @@ -25,10 +25,10 @@ exports.getGithubOAuthToken = async (code) => { return decoded; } catch (err) { - throw new AppError(400, 'fail', 'Invalid code'); + throw new AppError(400, 'Invalid code'); } }; -exports.getGithubOAuthUser = async (access_token) => { +export const getGithubOAuthUser = async (access_token: string) => { try { const { data } = await axios.get('https://api.github.com/user', { headers: { @@ -38,19 +38,19 @@ exports.getGithubOAuthUser = async (access_token) => { return data; } catch (err) { - throw new AppError(400, 'fail', 'Invalid access token'); + throw new AppError(400, 'Invalid access token'); } }; -exports.getGithubOAuthUserPrimaryEmail = async (access_token) => { +export const getGithubOAuthUserPrimaryEmail = async (access_token: string) => { try { const { data } = await axios.get('https://api.github.com/user/emails', { headers: { Authorization: `Bearer ${access_token}`, }, }); - const primaryEmail = data.find((email) => email.primary === true); + const primaryEmail = data.find((email: any) => email.primary === true); return primaryEmail.email; } catch (err) { - throw new AppError(400, 'fail', 'Invalid access token'); + throw new AppError(400, 'Invalid access token'); } }; diff --git a/backend-app/utils/authorization/role/role.js b/backend-app/utils/authorization/role/role.js deleted file mode 100644 index 5906d59..0000000 --- a/backend-app/utils/authorization/role/role.js +++ /dev/null @@ -1,163 +0,0 @@ -const AppError = require('../../app_error'); -const roleModel = require('../../../models/user/role_model'); -const Actions = require('../../../constants/actions'); -class Role { - constructor() { - this.roleModel = roleModel; - } - - _isRoleName(roleName) { - if (!roleName || typeof roleName !== 'string') - throw new AppError(400, 'fail', 'Invalid role name!'); - return; - } - /** - * Get all roles from database. - */ - async getRoles() { - const data = {}; - const roles = await this.roleModel.find(); - - roles.forEach((role) => { - data[role.name] = { - type: role.name, - authorities: role.authorities, - restrictions: role.restrictions, - }; - }); - return data; - } - /** - * Get role by name from database. - * @param {string} roleName - * @returns {Promise<{type: string, authorities: string[], restrictions: string[]}>} - */ - async getRoleByName(roleName) { - this._isRoleName(roleName); - const role = await this.roleModel.findOne({ name: roleName }); - if (!role) return null; - return { - type: role.name, - authorities: role.authorities, - restrictions: role.restrictions, - }; - } - /** - * Delete role by name from database. - * @param {string} roleName - * @returns {Promise<{type: string, authorities: string[], restrictions: string[]}>} - */ - async deleteRoleByName(roleName) { - this._isRoleName(roleName); - if (!this.getRoleByName(roleName)) - throw new AppError(404, 'fail', 'Role not found!'); - const deletedRole = await this.roleModel.findOneAndDelete( - { name: roleName }, - { new: true } - ); - return this._Exist( - { - type: deletedRole.name, - authorities: deletedRole.authorities, - restrictions: deletedRole.restrictions, - }, - new AppError(404, 'fail', 'Role not found!') - ); - } - /** - * Create role by name from database. - * @param {string} roleName - * @param {string[]} authorities - * @param {string[]} restrictions - * @returns {Promise<{type: string, authorities: string[], restrictions: string[]}>} - */ - async createRole(roleName, authorities, restrictions) { - this._isRoleName(roleName); - if (await this.getRoleByName(roleName)) return; - authorities || - [].forEach((authority) => { - if (!Object.values(Actions).includes(authority)) - throw new AppError( - 400, - 'fail', - `Invalid authority ${authority}` - ); - }); - restrictions || - [].forEach((restriction) => { - if (!Object.values(Actions).includes(restriction)) - throw new AppError( - 400, - 'fail', - `Invalid restriction ${restriction}` - ); - }); - const role = await this.roleModel.create({ - name: roleName, - authorities, - restrictions, - }); - return { - type: role.name, - authorities: role.authorities, - restrictions: role.restrictions, - }; - } - /** - * Delete default roles from database. - */ - async deleteDefaultRoles() { - await this.roleModel.deleteMany({ - name: { $in: ['SUPER_ADMIN', 'ADMIN', 'USER'] }, - }); - } - /** - * - * @param {string} roleName - * @param {string[]} authorities - * @param {string[]} restrictions - */ - async updateRoleByName(roleName, authorities, restrictions) { - authorities || - [].forEach((authority) => { - if (!Object.values(Actions).includes(authority)) - throw new AppError( - 400, - 'fail', - `Invalid authority ${authority}` - ); - }); - restrictions || - [].forEach((restriction) => { - if (!Object.values(Actions).includes(restriction)) - throw new AppError( - 400, - 'fail', - `Invalid restriction ${restriction}` - ); - }); - const exists = await this.roleModel.getRoleByName(name); - if (!exists) throw new AppError(404, 'fail', 'Role does not exist'); - - const updatedRole = await this.roleModel.findOneAndUpdate( - { - name: roleName, - }, - { - authorities: Array.from( - new Set([...exists.authorities, ...authorities]) - ), - restrictions: Array.from( - new Set([...exists.restrictions, ...restrictions]) - ), - } - ); - return { - type: updatedRole.name, - authorities: updatedRole.authorities, - restrictions: updatedRole.restrictions, - }; - } -} - -module.exports = Role; diff --git a/backend-app/utils/authorization/role/create_roles.js b/backend-app/utils/authorization/roles/create_roles.ts similarity index 55% rename from backend-app/utils/authorization/role/create_roles.js rename to backend-app/utils/authorization/roles/create_roles.ts index acd9860..c7edf62 100644 --- a/backend-app/utils/authorization/role/create_roles.js +++ b/backend-app/utils/authorization/roles/create_roles.ts @@ -1,25 +1,32 @@ -const Role = require('./role'); -const Actions = require('../../../constants/actions'); +import Actions from '../../../constants/actions'; +import Role from './role'; +import logger from '@utils/logger'; -const superAdmin = { +interface RoleType { + type: string; + authorities: string[]; + restrictions: string[]; +} + +const superAdmin: RoleType = { type: 'SUPER_ADMIN', authorities: Object.values(Actions), restrictions: [], }; -const admin = { +const admin: RoleType = { type: 'ADMIN', authorities: [Actions.BAN_USER, Actions.DELETE_USER], restrictions: [], }; -const user = { +const user: RoleType = { type: 'USER', authorities: [Actions.UPDATE_CALANDER], restrictions: [], }; -const createRoles = async () => { - const role = new Role(); - const roleArr = Object.keys(await role.getRoles()); +const createRoles = async (): Promise => { + const roles = await Role.getRoles(); + const roleArr = Object.keys(roles); try { if ( roleArr.length > 2 && @@ -28,23 +35,23 @@ const createRoles = async () => { roleArr.includes(user.type) ) return; - await role.createRole( + await Role.createRole( superAdmin.type, superAdmin.authorities, superAdmin.restrictions ); - await role.createRole( + await Role.createRole( admin.type, admin.authorities, admin.restrictions ); - await role.createRole(user.type, user.authorities, user.restrictions); - global.Logger.info( + await Role.createRole(user.type, user.authorities, user.restrictions); + logger.info( `[ ${superAdmin.type}, ${admin.type}, ${user.type} ] ROLES CREATED!` ); - // Logger.warn(await role.getRoles()); + // logger.warn(await role.getRoles()); } catch (err) { - global.Logger.error(err.stack); + logger.error(err.stack); } }; -module.exports = createRoles; +export default createRoles; diff --git a/backend-app/utils/authorization/roles/role.ts b/backend-app/utils/authorization/roles/role.ts new file mode 100644 index 0000000..a020a0c --- /dev/null +++ b/backend-app/utils/authorization/roles/role.ts @@ -0,0 +1,164 @@ +import AppError from '../../app_error'; +import roleModel from '../../../models/user/role_model'; +import Actions from '../../../constants/actions'; + +interface RoleData { + name: string; + authorities: string[]; + restrictions: string[]; +} + +function isRoleName(roleName: any): void { + if (!roleName || typeof roleName !== 'string') + throw new AppError(400, 'Invalid role name!'); +} + +/** + * Get all roles from database. + */ +async function getRoles(): Promise<{ [key: string]: RoleData }> { + const data: { [key: string]: RoleData } = {}; + const roles = await roleModel.find(); + + roles.forEach((role) => { + data[role.name] = { + name: role.name, + authorities: role.authorities, + restrictions: role.restrictions, + }; + }); + return data; +} + +/** + * Get role by name from database. + * @param {string} roleName + * @returns {Promise} + */ +async function getRoleByName(roleName: string): Promise { + isRoleName(roleName); + const role = await roleModel.findOne({ name: roleName }); + if (!role) return null; + return { + name: role.name, + authorities: role.authorities, + restrictions: role.restrictions, + }; +} + +/** + * Delete role by name from database. + * @param {string} roleName + * @returns {Promise} + */ +async function deleteRoleByName(roleName: string): Promise { + isRoleName(roleName); + const role = await getRoleByName(roleName); + if (!role) throw new AppError(404, 'Role not found!'); + const deletedRole = await roleModel.findOneAndDelete( + { name: roleName }, + { new: true } + ); + if (!deletedRole) throw new AppError(404, 'Role not found!'); + return { + name: deletedRole.name, + authorities: deletedRole.authorities, + restrictions: deletedRole.restrictions, + }; +} + +/** + * Create role by name from database. + * @param {string} roleName + * @param {string[]} authorities + * @param {string[]} restrictions + * @returns {Promise} + */ +async function createRole( + roleName: string, + authorities: string[] = [], + restrictions: string[] = [] +): Promise { + isRoleName(roleName); + if (await getRoleByName(roleName)) + throw new AppError(400, 'Role already exists'); + authorities.forEach((authority) => { + if (!Object.values(Actions).includes(authority)) + throw new AppError(400, `Invalid authority ${authority}`); + }); + restrictions.forEach((restriction) => { + if (!Object.values(Actions).includes(restriction)) + throw new AppError(400, `Invalid restriction ${restriction}`); + }); + const role = await roleModel.create({ + name: roleName, + authorities, + restrictions, + }); + return { + name: role.name, + authorities: role.authorities, + restrictions: role.restrictions, + }; +} + +/** + * Delete default roles from database. + */ +async function deleteDefaultRoles(): Promise { + await roleModel.deleteMany({ + name: { $in: ['SUPER_ADMIN', 'ADMIN', 'USER'] }, + }); +} + +/** + * + * @param {string} roleName + * @param {string[]} authorities + * @param {string[]} restrictions + */ +async function updateRoleByName( + roleName: string, + authorities: string[] = [], + restrictions: string[] = [] +): Promise { + authorities.forEach((authority) => { + if (!Object.values(Actions).includes(authority)) + throw new AppError(400, `Invalid authority ${authority}`); + }); + restrictions.forEach((restriction) => { + if (!Object.values(Actions).includes(restriction)) + throw new AppError(400, `Invalid restriction ${restriction}`); + }); + const exists = await getRoleByName(roleName); + if (!exists) throw new AppError(404, 'Role does not exist'); + + const updatedRole = await roleModel.findOneAndUpdate( + { + name: roleName, + }, + { + authorities: Array.from( + new Set([...exists.authorities, ...authorities]) + ), + restrictions: Array.from( + new Set([...exists.restrictions, ...restrictions]) + ), + } + ); + if (!updatedRole) throw new AppError(404, 'Role not found!'); + return { + name: updatedRole.name, + authorities: updatedRole.authorities, + restrictions: updatedRole.restrictions, + }; +} + +export default { + getRoles, + getRoleByName, + deleteRoleByName, + createRole, + deleteDefaultRoles, + updateRoleByName, +}; diff --git a/backend-app/utils/authorization/validate_actions.js b/backend-app/utils/authorization/validate_actions.ts similarity index 56% rename from backend-app/utils/authorization/validate_actions.js rename to backend-app/utils/authorization/validate_actions.ts index 8871671..5c3158a 100644 --- a/backend-app/utils/authorization/validate_actions.js +++ b/backend-app/utils/authorization/validate_actions.ts @@ -1,11 +1,11 @@ -const Actions = require('../../constants/actions'); +import Actions from '@constants/actions'; /** * Validate all the actions in the array * @param {string[]} actions * @returns boolean */ -const validateActions = (actions) => +const validateActions = (actions: string[]): boolean => actions.every((action) => Object.values(Actions).includes(action)); -module.exports = validateActions; +export default validateActions; diff --git a/backend-app/utils/create_default_user.js b/backend-app/utils/create_default_user.js deleted file mode 100644 index 7fab748..0000000 --- a/backend-app/utils/create_default_user.js +++ /dev/null @@ -1,26 +0,0 @@ -// create admin user if not exists - -const User = require('../models/user/user_model'); -const { ADMIN_EMAIL, ADMIN_PASSWORD } = require('../config/app_config'); -const { SUPER_ADMIN } = require('../constants/default_roles'); - -const createAdminUser = async () => { - try { - const user = await User.findOne({ email: ADMIN_EMAIL }); - if (!user) { - await User.create({ - name: 'Supper Admin', - email: ADMIN_EMAIL, - password: ADMIN_PASSWORD, - roles: [SUPER_ADMIN.type], - authorities: SUPER_ADMIN.authorities, - restrictions: SUPER_ADMIN.restrictions, - active: true, - }); - } - } catch (err) { - Logger.error(err.stack); - } -}; - -module.exports = createAdminUser; diff --git a/backend-app/utils/create_default_user.ts b/backend-app/utils/create_default_user.ts new file mode 100644 index 0000000..d6f166e --- /dev/null +++ b/backend-app/utils/create_default_user.ts @@ -0,0 +1,26 @@ +import User from '@models/user/user_model'; +import { ADMIN_EMAIL, ADMIN_PASSWORD } from '@config/app_config'; +import logger from '@utils/logger'; +import Role from '@utils/authorization/roles/role'; + +const createAdminUser = async () => { + try { + const user = await User.findOne({ email: ADMIN_EMAIL }); + if (!user) { + const roles = await Role.getRoles(); + await User.create({ + name: 'Supper Admin', + email: ADMIN_EMAIL, + password: ADMIN_PASSWORD, + roles: [roles.SUPER_ADMIN.name], + authorities: roles.SUPER_ADMIN.authorities, + restrictions: roles.SUPER_ADMIN.restrictions, + active: true, + }); + } + } catch (err) { + logger.error(err.stack); + } +}; + +export default createAdminUser; diff --git a/backend-app/utils/logger.js b/backend-app/utils/logger.ts similarity index 81% rename from backend-app/utils/logger.js rename to backend-app/utils/logger.ts index b5d7e5c..2b60a1c 100644 --- a/backend-app/utils/logger.js +++ b/backend-app/utils/logger.ts @@ -3,16 +3,16 @@ */ import { createLogger, transports } from 'winston'; import DailyRotateFile from 'winston-daily-rotate-file'; -import { fileOptions, consoleOptions } from '../config/logger_config'; +import { fileOptions, consoleOptions } from '@config/logger_config'; // Define the transport for the logger const consoleTransport = new transports.Console(consoleOptions); const fileTransport = new DailyRotateFile(fileOptions); -const Logger = createLogger({ +const logger = createLogger({ transports: [consoleTransport, fileTransport], // add the transport to the logger exceptionHandlers: [fileTransport], exitOnError: false, // do not exit on handled exceptions }); // Export the logger -globalThis.Logger = Logger; +export default logger; diff --git a/backend-app/utils/register_paths.js b/backend-app/utils/register_paths.js deleted file mode 100644 index 6992c7a..0000000 --- a/backend-app/utils/register_paths.js +++ /dev/null @@ -1,8 +0,0 @@ -const tsConfig = require('../tsconfig.json'); -const tsConfigPaths = require('tsconfig-paths'); - -const baseUrl = './'; -const cleanup = tsConfigPaths.register({ - baseUrl, - paths: tsConfig.compilerOptions.paths, -}); diff --git a/backend-app/utils/register_paths.ts b/backend-app/utils/register_paths.ts new file mode 100644 index 0000000..fee967a --- /dev/null +++ b/backend-app/utils/register_paths.ts @@ -0,0 +1,9 @@ +import * as tsConfigPaths from 'tsconfig-paths'; +import * as tsConfig from '../tsconfig.json'; +import * as path from 'path'; + +const baseUrl = path.join(__dirname, '../'); +tsConfigPaths.register({ + baseUrl, + paths: tsConfig.compilerOptions.paths, +}); diff --git a/backend-app/utils/sanitize_request_body.js b/backend-app/utils/sanitize_request_body.js deleted file mode 100644 index 9cbeace..0000000 --- a/backend-app/utils/sanitize_request_body.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * sanitize request body - * @param {Model} Model - The mongoose model - * @param {Object} body - The request body - * @returns {Object} - The sanitized request body - * @description - This function sanitizes the request body by removing any field that is not in the schema - * @example - * const sanitizedBody = sanitizeRequestBody(User, req.body); - */ -const sanitizeRequestBody = (schema, body) => { - const sanitizedData = {}; - - for (const key in body) { - if (schema.path(key)) { - sanitizedData[key] = schema.path(key).applySetters(body[key]); - } - } - - return sanitizedData; -}; - -module.exports = sanitizeRequestBody; diff --git a/backend-app/utils/searchCookie.js b/backend-app/utils/searchCookie.js deleted file mode 100644 index 6e9532e..0000000 --- a/backend-app/utils/searchCookie.js +++ /dev/null @@ -1,9 +0,0 @@ -const searchCookies = (req, cookieName) => { - const cookies = - Object.keys(req.signedCookies).length > 0 ? req.signedCookies : false; - if (!cookies) return false; - const cookie = cookies[cookieName]; - if (!cookie) return false; - return cookie; -}; -module.exports = searchCookies; diff --git a/backend-app/utils/searchCookie.ts b/backend-app/utils/searchCookie.ts new file mode 100644 index 0000000..355aada --- /dev/null +++ b/backend-app/utils/searchCookie.ts @@ -0,0 +1,14 @@ +import { Request } from 'express'; + +const searchCookies = ( + req: Request, + cookieName: string +): string | undefined => { + const cookies = req.cookies; + if (!cookies || !cookies[cookieName]) { + return undefined; + } + return cookies[cookieName]; +}; + +export default searchCookies; diff --git a/backend-app/utils/swagger/index.js b/backend-app/utils/swagger/index.js deleted file mode 100644 index 3e71a59..0000000 --- a/backend-app/utils/swagger/index.js +++ /dev/null @@ -1,53 +0,0 @@ -const swaggerUi = require('swagger-ui-express'); -const { PORT, CURRENT_ENV } = require('../../config/app_config'); -const path = require('path'); -const YAML = require('yamljs'); -const mergeYamlFiles = require('./merge_yaml_files'); -// Path to the swagger annotations directory -const docsDirPath = path.join(__dirname, '../../docs/api_docs/'); -// Path to the swagger.yaml file -const swaggerSpecPath = path.join(__dirname, '../../swagger.yaml'); -// Load the swagger.yaml file -const swaggerSpec = YAML.load(swaggerSpecPath); -// Merge the swagger.yaml file with the swagger annotations -swaggerSpec.paths = mergeYamlFiles(docsDirPath); -swaggerSpec.servers = [ - { - url: `http://localhost:${PORT}/api`, - description: 'Development server', - }, -]; -const swaggerUiOptions = { - swaggerOptions: { - tryItOutEnabled: true, - // Show the request duration (in ms) in the responses - displayRequestDuration: true, - // other advanced settings - showExtensions: true, - filter: true, - showCommonExtensions: true, - layout: 'BaseLayout', - deepLinking: true, - }, -}; -/** - * This function configures the swagger documentation - * @param { application } app - The express application - * @returns {void} - */ -const swaggerDocs = (app) => { - if (CURRENT_ENV === 'production') return; - app.use( - '/docs', - swaggerUi.serve, - swaggerUi.setup(swaggerSpec, swaggerUiOptions) - ); - // Get docs in JSON format - app.get('/docs-json', (_, res) => { - res.setHeader('Content-Type', 'application/json'); - res.send(swaggerSpec); - }); - global.Logger.info(`Swagger available at /docs /docs-json`); -}; - -module.exports = swaggerDocs; diff --git a/backend-app/utils/swagger/index.ts b/backend-app/utils/swagger/index.ts new file mode 100644 index 0000000..0404646 --- /dev/null +++ b/backend-app/utils/swagger/index.ts @@ -0,0 +1,21 @@ +import { CURRENT_ENV } from '@config/app_config'; +import { IRes } from '@interfaces/vendors'; +import swaggerUi from 'swagger-ui-express'; +import * as swaggerjson from '@root/swagger.json'; + +/** + * This function configures the swagger documentation + * @param { application } app - The express application + * @returns {void} + */ +const swaggerDocs = (app: any): void => { + if (CURRENT_ENV === 'production') return; + app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerjson)); + // Get docs in JSON format + app.get('/docs-json', (_: any, res: IRes) => { + res.setHeader('Content-Type', 'application/json'); + res.send(swaggerjson); + }); +}; + +export default swaggerDocs; diff --git a/backend-app/utils/swagger/merge_yaml_files.js b/backend-app/utils/swagger/merge_yaml_files.js deleted file mode 100644 index 7b0bf04..0000000 --- a/backend-app/utils/swagger/merge_yaml_files.js +++ /dev/null @@ -1,28 +0,0 @@ -const path = require('path'); -const fs = require('fs'); -const YAML = require('yamljs'); - -/** - * Merges all the YAML files in a directory - * @param {String} directoryPath - */ -const mergeYamlFiles = (directoryPath) => { - const mergedYamlObject = {}; - // check directory exists - if (!fs.existsSync(directoryPath)) { - Logger.error(`Directory ${directoryPath} does not exist`); - fs.mkdirSync(directoryPath); - } - const files = fs.readdirSync(directoryPath); - files.forEach((file) => { - if (path.extname(file) !== '.yaml') - Logger.warn(`Skipping file ${file} as it is not a YAML file`); - const yamlFilePath = path.join(directoryPath, file); - const fileContents = fs.readFileSync(yamlFilePath, 'utf8'); - const yamlData = YAML.parse(fileContents); - Object.assign(mergedYamlObject, yamlData); - }); - return mergedYamlObject; -}; - -module.exports = mergeYamlFiles; diff --git a/backend-app/utils/swagger/swaggergenerator.js b/backend-app/utils/swagger/swaggergenerator.js deleted file mode 100644 index 92dd6af..0000000 --- a/backend-app/utils/swagger/swaggergenerator.js +++ /dev/null @@ -1,35 +0,0 @@ -const swaggerAutogen = require('swagger-autogen'); -require('../logger'); - -const outputFile = './docs/swagger-output.json'; - -const options = { - disableLogs: true, -}; - -/** - * - * @param {string} tag tag name for swagger docs - * @param {string} routePath path of route file - * @returns {Promise} - * */ -const register = async (tag, routePath) => { - await swaggerAutogen(options)(outputFile, [routePath]); - const fs = require('fs'); - const rawdata = fs.readFileSync(outputFile); - const s = JSON.parse(rawdata); - // to all request add tag tag - for (const [key, value] of Object.entries(s.paths)) { - for (const [method, data] of Object.entries(value)) { - data.tags = [tag]; - } - } - const jsYaml = require('js-yaml'); - const yamlData = jsYaml.dump(s.paths); - // save to swagger2.yaml - fs.writeFileSync(`./docs/api_docs/${tag}.yaml`, yamlData); - fs.unlinkSync(outputFile); - Logger.info(`Swagger docs for route [ ${tag} ] generated successfully`); -}; - -exports.register = register;