├── backend
├── ArquitecturaAPI.png
├── src
│ ├── constants
│ │ └── roles.constants.js
│ ├── config
│ │ ├── .env.example
│ │ ├── configEnv.js
│ │ ├── configDB.js
│ │ └── initialSetup.js
│ ├── routes
│ │ ├── auth.routes.js
│ │ ├── index.routes.js
│ │ └── user.routes.js
│ ├── models
│ │ ├── role.model.js
│ │ └── user.model.js
│ ├── utils
│ │ ├── errorHandler.js
│ │ └── resHandler.js
│ ├── schema
│ │ ├── auth.schema.js
│ │ └── user.schema.js
│ ├── middlewares
│ │ ├── authorization.middleware.js
│ │ └── authentication.middleware.js
│ ├── server.js
│ ├── controllers
│ │ ├── auth.controller.js
│ │ └── user.controller.js
│ └── services
│ │ ├── auth.service.js
│ │ └── user.service.js
├── .prettierrc.json
├── package.json
├── .eslintrc.json
├── .gitignore
├── README.md
└── package-lock.json
├── frontend
├── src
│ ├── routes
│ │ ├── App.jsx
│ │ ├── Login.jsx
│ │ ├── ErrorPage.jsx
│ │ └── Root.jsx
│ ├── services
│ │ ├── root.service.js
│ │ └── auth.service.js
│ ├── index.css
│ ├── main.jsx
│ ├── context
│ │ └── AuthContext.jsx
│ ├── components
│ │ └── LoginForm.jsx
│ └── assets
│ │ └── react.svg
├── vite.config.js
├── .gitignore
├── index.html
├── README.md
├── public
│ ├── .eslintrc.cjs
│ └── vite.svg
└── package.json
├── README.md
└── .gitignore
/backend/ArquitecturaAPI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ubiobio/Template-ISW-Proyecto-2023/HEAD/backend/ArquitecturaAPI.png
--------------------------------------------------------------------------------
/backend/src/constants/roles.constants.js:
--------------------------------------------------------------------------------
1 | /** Roles permitidos por la base de datos */
2 | const ROLES = ["user", "admin"];
3 |
4 | export default ROLES;
5 |
--------------------------------------------------------------------------------
/backend/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": false,
3 | "trailingComma": "all",
4 | "tabWidth": 2,
5 | "semi": true,
6 | "arrowParens": "always"
7 | }
8 |
--------------------------------------------------------------------------------
/frontend/src/routes/App.jsx:
--------------------------------------------------------------------------------
1 | function App() {
2 | return (
3 | <>
4 |
Pagina principal
5 | >
6 | );
7 | }
8 |
9 | export default App;
10 |
--------------------------------------------------------------------------------
/frontend/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/backend/src/config/.env.example:
--------------------------------------------------------------------------------
1 | PORT=Inserte el puerto de su servidor
2 | HOST=localhost
3 | DB_URL=Inserte su link de mongo Atlas
4 | ACCESS_JWT_SECRET=Inserte el secreto de su JWT
5 | REFRESH_JWT_SECRET=Inserte un secreto distinto de su JWT
6 |
--------------------------------------------------------------------------------
/frontend/src/services/root.service.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | const API_URL = import.meta.env.VITE_BASE_URL || 'http://localhost:5000/api';
4 |
5 | const instance = axios.create({
6 | baseURL: API_URL,
7 | headers: {
8 | 'Content-Type': 'application/json',
9 | },
10 | withCredentials: true,
11 | });
12 |
13 | export default instance;
14 |
--------------------------------------------------------------------------------
/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/frontend/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Titulo
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/frontend/README.md:
--------------------------------------------------------------------------------
1 | # React + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
--------------------------------------------------------------------------------
/frontend/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | -webkit-text-size-adjust: 100%;
15 | }
16 |
17 | a {
18 | text-decoration: inherit;
19 | }
20 |
--------------------------------------------------------------------------------
/frontend/src/routes/Login.jsx:
--------------------------------------------------------------------------------
1 | import LoginForm from '../components/LoginForm';
2 | import { useNavigate } from 'react-router-dom';
3 |
4 | function Login() {
5 | const navigate = useNavigate();
6 |
7 | if (localStorage.getItem('user')) {
8 | return (
9 | <>
10 | Ya estas logeado!
11 |
12 | >
13 | );
14 | }
15 |
16 | return (
17 |
18 |
Inicia sesion!
19 |
20 |
21 | );
22 | }
23 |
24 | export default Login;
25 |
--------------------------------------------------------------------------------
/backend/src/routes/auth.routes.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // Importa el modulo 'express' para crear las rutas
3 | import { Router } from "express";
4 |
5 | /** Controlador de autenticación */
6 | import authController from "../controllers/auth.controller.js";
7 |
8 | /** Instancia del enrutador */
9 | const router = Router();
10 |
11 | // Define las rutas para la autenticación
12 | router.post("/login", authController.login);
13 | router.post("/logout", authController.logout);
14 | router.get("/refresh", authController.refresh);
15 |
16 | // Exporta el enrutador
17 | export default router;
18 |
--------------------------------------------------------------------------------
/frontend/public/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true },
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:react/recommended',
7 | 'plugin:react/jsx-runtime',
8 | 'plugin:react-hooks/recommended',
9 | ],
10 | ignorePatterns: ['dist', '.eslintrc.cjs'],
11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
12 | settings: { react: { version: '18.2' } },
13 | plugins: ['react-refresh'],
14 | rules: {
15 | 'react-refresh/only-export-components': [
16 | 'warn',
17 | { allowConstantExport: true },
18 | ],
19 | },
20 | }
21 |
--------------------------------------------------------------------------------
/backend/src/models/role.model.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // Importa el modulo 'mongoose' para crear la conexion a la base de datos
3 | import { Schema, model } from "mongoose";
4 | import ROLES from "../constants/roles.constants.js";
5 |
6 | // Crea el esquema de la coleccion 'roles'
7 | const roleSchema = new Schema(
8 | {
9 | name: {
10 | type: String,
11 | enum: ROLES,
12 | required: true,
13 | },
14 | },
15 | {
16 | versionKey: false,
17 | },
18 | );
19 |
20 | // Crea el modelo de datos 'Role' a partir del esquema 'roleSchema'
21 | const Role = model("Role", roleSchema);
22 |
23 | export default Role;
24 |
--------------------------------------------------------------------------------
/frontend/src/routes/ErrorPage.jsx:
--------------------------------------------------------------------------------
1 | import { useRouteError } from 'react-router-dom';
2 |
3 | const ErrorPage = () => {
4 | const error = useRouteError();
5 |
6 | /**
7 | * Este mensaje de error, está pensado para los desarrolladores.
8 | * En un entorno de producción, no se debería mostrar este mensaje o almenos
9 | * no de esta forma.
10 | */
11 | console.error({
12 | status: error.status,
13 | statusText: error.statusText,
14 | message: error.message ? error.message : 'No message',
15 | });
16 |
17 | return (
18 |
19 |
Oops!
20 |
Sorry, un error inesperado a ocurrido.
21 |
22 | );
23 | };
24 |
25 | export default ErrorPage;
26 |
--------------------------------------------------------------------------------
/backend/src/utils/errorHandler.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | /**
4 | * Manejador de errores fatales
5 | * @param {Object} error Objecto con las especificaciones del error
6 | * @param {String} msg Mensaje para dar contexto al error
7 | */
8 | function handleFatalError(error, msg) {
9 | console.log("[FATAL ERROR] Apagando servidor \n", msg);
10 | console.error(error);
11 | process.exit(1);
12 | }
13 |
14 | /**
15 | * Manejador de errores
16 | * @param {Object} error Objecto con las especificaciones del error
17 | * @param {String} msg Mensaje para dar contexto al error
18 | */
19 | function handleError(error, msg) {
20 | console.log("❌ [ERROR] A ocurrido un error en: \n📁", msg);
21 | console.error("🗯 " + error.message);
22 | }
23 |
24 | export { handleFatalError, handleError };
25 |
--------------------------------------------------------------------------------
/backend/src/routes/index.routes.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // Importa el modulo 'express' para crear las rutas
3 | import { Router } from "express";
4 |
5 | /** Enrutador de usuarios */
6 | import userRoutes from "./user.routes.js";
7 |
8 | /** Enrutador de autenticación */
9 | import authRoutes from "./auth.routes.js";
10 |
11 | /** Middleware de autenticación */
12 | import authenticationMiddleware from "../middlewares/authentication.middleware.js";
13 |
14 | /** Instancia del enrutador */
15 | const router = Router();
16 |
17 | // Define las rutas para los usuarios /api/usuarios
18 | router.use("/users", authenticationMiddleware, userRoutes);
19 | // Define las rutas para la autenticación /api/auth
20 | router.use("/auth", authRoutes);
21 |
22 | // Exporta el enrutador
23 | export default router;
24 |
--------------------------------------------------------------------------------
/frontend/src/main.jsx:
--------------------------------------------------------------------------------
1 | import ReactDOM from 'react-dom/client';
2 | import App from './routes/App.jsx';
3 | import './index.css';
4 | import { createBrowserRouter, RouterProvider } from 'react-router-dom';
5 | import Root from './routes/Root.jsx';
6 | import ErrorPage from './routes/ErrorPage.jsx';
7 | import Login from './routes/Login.jsx';
8 |
9 | const router = createBrowserRouter([
10 | {
11 | path: '/',
12 | element: ,
13 | errorElement: ,
14 | children: [
15 | {
16 | path: '/',
17 | element: ,
18 | },
19 | ],
20 | },
21 | {
22 | path: '/auth',
23 | element: ,
24 | },
25 | ]);
26 |
27 | ReactDOM.createRoot(document.getElementById('root')).render(
28 |
29 | );
30 |
--------------------------------------------------------------------------------
/backend/src/config/configEnv.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // Import the 'path' module to get the absolute path of the .env file
3 | import path from "node:path";
4 | const __dirname = import.meta.dirname;
5 |
6 | /** Get the absolute path of the .env file. */
7 | const envFilePath = path.resolve(__dirname, ".env");
8 | // Load environment variables from the .env file
9 | import dotenv from "dotenv";
10 | dotenv.config({ path: envFilePath });
11 |
12 | /** Server port */
13 | export const PORT = process.env.PORT;
14 | /** Server host */
15 | export const HOST = process.env.HOST;
16 | /** Database URL */
17 | export const DB_URL = process.env.DB_URL;
18 | /** Access token secret */
19 | export const ACCESS_JWT_SECRET = process.env.ACCESS_JWT_SECRET;
20 | /** Refresh token secret */
21 | export const REFRESH_JWT_SECRET = process.env.REFRESH_JWT_SECRET;
22 |
--------------------------------------------------------------------------------
/backend/src/config/configDB.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // Importa el modulo 'mongoose' para crear la conexion a la base de datos
3 | import { connect } from "mongoose";
4 |
5 | // Agregamos la configuracion de las variables de entorno
6 | import { DB_URL } from "./configEnv.js";
7 | import { handleError } from "../utils/errorHandler.js";
8 |
9 | /**
10 | * Establece la conexión con la base de datos.
11 | * @async
12 | * @function setupDB
13 | * @throws {Error} Si no se puede conectar a la base de datos.
14 | * @returns {Promise} Una promesa que se resuelve cuando se establece la conexión con la base de datos.
15 | */
16 |
17 | async function setupDB() {
18 | try {
19 | await connect(DB_URL);
20 | console.log("=> Conectado a la base de datos");
21 | } catch (err) {
22 | handleError(err, "/configDB.js -> setupDB");
23 | }
24 | }
25 |
26 | export { setupDB };
27 |
--------------------------------------------------------------------------------
/frontend/src/context/AuthContext.jsx:
--------------------------------------------------------------------------------
1 | import { createContext, useContext, useEffect } from 'react';
2 | import { useNavigate } from 'react-router-dom';
3 |
4 | const AuthContext = createContext();
5 |
6 | // eslint-disable-next-line react-refresh/only-export-components
7 | export const useAuth = () => useContext(AuthContext);
8 |
9 | // eslint-disable-next-line react/prop-types
10 | export function AuthProvider({ children }) {
11 | const navigate = useNavigate();
12 |
13 | const user = JSON.parse(localStorage.getItem('user')) || '';
14 | const isAuthenticated = user ? true : false;
15 |
16 | useEffect(() => {
17 | if (!isAuthenticated) {
18 | navigate('/auth');
19 | }
20 | }, [isAuthenticated, navigate]);
21 |
22 | return (
23 |
24 | {children}
25 |
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/frontend/src/routes/Root.jsx:
--------------------------------------------------------------------------------
1 | import { Outlet } from 'react-router-dom';
2 | import { useNavigate } from 'react-router-dom';
3 | import { logout } from '../services/auth.service';
4 | import { AuthProvider, useAuth } from '../context/AuthContext';
5 |
6 | function Root() {
7 | return (
8 |
9 |
10 |
11 | );
12 | }
13 |
14 | function PageRoot() {
15 | const navigate = useNavigate();
16 |
17 | const handleLogout = () => {
18 | logout();
19 | navigate('/auth');
20 | };
21 |
22 | const { user } = useAuth();
23 |
24 | return (
25 |
26 |
27 |
Aqui deberia ir un header
28 |
Estas logeado como: {user.email}
29 |
30 |
31 |
32 |
33 | );
34 | }
35 |
36 | export default Root;
37 |
--------------------------------------------------------------------------------
/backend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "api-node",
3 | "version": "1.0.0",
4 | "type": "module",
5 | "description": "Template backend",
6 | "main": "src/server.js",
7 | "scripts": {
8 | "start": "nodemon src/server.js",
9 | "dev": "nodemon src/server.js"
10 | },
11 | "keywords": [
12 | "node",
13 | "backend",
14 | "http"
15 | ],
16 | "author": "Camilo saez",
17 | "license": "MIT",
18 | "dependencies": {
19 | "bcryptjs": "2.4.3",
20 | "cookie-parser": "1.4.6",
21 | "cors": "2.8.5",
22 | "dotenv": "^16.4.4",
23 | "express": "4.18.2",
24 | "joi": "17.10.2",
25 | "jsonwebtoken": "9.0.2",
26 | "mongoose": "^8.1.0",
27 | "morgan": "1.10.0"
28 | },
29 | "devDependencies": {
30 | "eslint": "^8.56.0",
31 | "eslint-config-google": "0.14.0",
32 | "jsdoc": "4.0.2",
33 | "nodemon": "^3.0.3",
34 | "prettier": "^3.2.5"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/backend/src/schema/auth.schema.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import Joi from "joi";
4 |
5 | /**
6 | * Esquema de validación para el cuerpo de la solicitud de inicio de sesión.
7 | * @constant {Object}
8 | */
9 | const authLoginBodySchema = Joi.object({
10 | email: Joi.string().email().required().messages({
11 | "string.empty": "El email no puede estar vacío.",
12 | "any.required": "El email es obligatorio.",
13 | "string.base": "El email debe ser de tipo string.",
14 | "string.email": "El email debe tener un formato válido.",
15 | }),
16 | password: Joi.string().required().messages({
17 | "string.empty": "La contraseña no puede estar vacía.",
18 | "any.required": "La contraseña es obligatoria.",
19 | "string.base": "La contraseña debe ser de tipo string.",
20 | }),
21 | }).messages({
22 | "object.unknown": "No se permiten propiedades adicionales.",
23 | });
24 |
25 | export { authLoginBodySchema };
26 |
--------------------------------------------------------------------------------
/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontend",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "axios": "^1.5.1",
14 | "js-cookie": "^3.0.5",
15 | "jwt-decode": "^3.1.2",
16 | "react": "^18.2.0",
17 | "react-dom": "^18.2.0",
18 | "react-hook-form": "^7.47.0",
19 | "react-router-dom": "^6.17.0"
20 | },
21 | "devDependencies": {
22 | "@types/react": "^18.2.15",
23 | "@types/react-dom": "^18.2.7",
24 | "@vitejs/plugin-react": "^4.0.3",
25 | "eslint": "^8.45.0",
26 | "eslint-plugin-react": "^7.32.2",
27 | "eslint-plugin-react-hooks": "^4.6.0",
28 | "eslint-plugin-react-refresh": "^0.4.3",
29 | "vite": "^4.4.5"
30 | }
31 | }
--------------------------------------------------------------------------------
/frontend/src/components/LoginForm.jsx:
--------------------------------------------------------------------------------
1 | import { useNavigate } from 'react-router-dom';
2 | import { useForm } from 'react-hook-form';
3 | import { login } from '../services/auth.service';
4 |
5 | function LoginForm() {
6 | const navigate = useNavigate();
7 |
8 | const {
9 | register,
10 | handleSubmit,
11 | formState: { errors },
12 | } = useForm();
13 |
14 | const onSubmit = (data) => {
15 | login(data).then(() => {
16 | navigate('/');
17 | });
18 | };
19 |
20 | return (
21 |
35 | );
36 | }
37 |
38 | export default LoginForm;
39 |
--------------------------------------------------------------------------------
/backend/src/routes/user.routes.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // Importa el modulo 'express' para crear las rutas
3 | import { Router } from "express";
4 |
5 | /** Controlador de usuarios */
6 | import usuarioController from "../controllers/user.controller.js";
7 |
8 | /** Middlewares de autorización */
9 | import { isAdmin } from "../middlewares/authorization.middleware.js";
10 |
11 | /** Middleware de autenticación */
12 | import authenticationMiddleware from "../middlewares/authentication.middleware.js";
13 |
14 | /** Instancia del enrutador */
15 | const router = Router();
16 |
17 | // Define el middleware de autenticación para todas las rutas
18 | router.use(authenticationMiddleware);
19 | // Define las rutas para los usuarios
20 | router.get("/", isAdmin, usuarioController.getUsers);
21 | router.post("/", isAdmin, usuarioController.createUser);
22 | router.get("/:id", usuarioController.getUserById);
23 | router.put("/:id", isAdmin, usuarioController.updateUser);
24 | router.delete("/:id", isAdmin, usuarioController.deleteUser);
25 |
26 | // Exporta el enrutador
27 | export default router;
28 |
--------------------------------------------------------------------------------
/backend/src/middlewares/authorization.middleware.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // Autorizacion - Comprobar el rol del usuario
3 | import User from "../models/user.model.js";
4 | import Role from "../models/role.model.js";
5 | import { respondError } from "../utils/resHandler.js";
6 | import { handleError } from "../utils/errorHandler.js";
7 |
8 | /**
9 | * Comprueba si el usuario es administrador
10 | * @param {Object} req - Objeto de petición
11 | * @param {Object} res - Objeto de respuesta
12 | * @param {Function} next - Función para continuar con la siguiente función
13 | */
14 | async function isAdmin(req, res, next) {
15 | try {
16 | const user = await User.findOne({ email: req.email });
17 | const roles = await Role.find({ _id: { $in: user.roles } });
18 | for (let i = 0; i < roles.length; i++) {
19 | if (roles[i].name === "admin") {
20 | next();
21 | return;
22 | }
23 | }
24 | return respondError(
25 | req,
26 | res,
27 | 401,
28 | "Se requiere un rol de administrador para realizar esta acción",
29 | );
30 | } catch (error) {
31 | handleError(error, "authorization.middleware -> isAdmin");
32 | }
33 | }
34 |
35 | export { isAdmin };
36 |
--------------------------------------------------------------------------------
/frontend/src/services/auth.service.js:
--------------------------------------------------------------------------------
1 | import axios from './root.service';
2 | import cookies from 'js-cookie';
3 | import jwtDecode from 'jwt-decode';
4 |
5 | export const login = async ({ email, password }) => {
6 | try {
7 | const response = await axios.post('auth/login', {
8 | email,
9 | password,
10 | });
11 | const { status, data } = response;
12 | if (status === 200) {
13 | const { email, roles } = await jwtDecode(data.data.accessToken);
14 | localStorage.setItem('user', JSON.stringify({ email, roles }));
15 | axios.defaults.headers.common[
16 | 'Authorization'
17 | ] = `Bearer ${data.data.accessToken}`;
18 | }
19 | } catch (error) {
20 | console.log(error);
21 | }
22 | };
23 |
24 | export const logout = () => {
25 | localStorage.removeItem('user');
26 | delete axios.defaults.headers.common['Authorization'];
27 | cookies.remove('jwt');
28 | };
29 |
30 | export const test = async () => {
31 | try {
32 | const response = await axios.get('/users');
33 | const { status, data } = response;
34 | if (status === 200) {
35 | console.log(data.data);
36 | }
37 | } catch (error) {
38 | console.log(error);
39 | }
40 | };
41 |
--------------------------------------------------------------------------------
/backend/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "es6": true,
4 | "node": true
5 | },
6 | "extends": ["google"],
7 | "parserOptions": {
8 | "ecmaVersion": "latest",
9 | "sourceType": "module"
10 | },
11 | "rules": {
12 | "require-jsdoc": [
13 | "warn",
14 | {
15 | "require": {
16 | "FunctionDeclaration": true,
17 | "MethodDefinition": true,
18 | "ClassDeclaration": true,
19 | "ArrowFunctionExpression": true,
20 | "FunctionExpression": true
21 | }
22 | }
23 | ],
24 | "indent": "off",
25 | "new-cap": "off",
26 | "object-curly-spacing": ["error", "always"],
27 | "array-bracket-spacing": "off",
28 | "max-len": [
29 | "error",
30 | {
31 | "code": 100,
32 | "tabWidth": 2,
33 | "comments": 150
34 | }
35 | ],
36 | "valid-jsdoc": "off",
37 | "no-console": "warn",
38 | "quotes": ["error", "double"],
39 | "operator-linebreak": [
40 | "warn",
41 | "before",
42 | {
43 | "overrides": {
44 | ":": "before",
45 | "=": "after"
46 | }
47 | }
48 | ],
49 | "no-trailing-spaces": "off",
50 | "linebreak-style": "off"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > [!TIP]
2 | > Recomiendo utilizar el template, ya que les ahorrará tiempo al tener la implementación del inicio de sesión lista.
3 | # Template Proyecto Ingenieria de Software 👨💻
4 |
5 | Este template está diseñado para proporcionar a los estudiantes del curso de Ingeniería de Software una base al iniciar su proyecto, incluyendo un backend con funcionalidad de inicio de sesión y un frontend correspondiente.
6 |
7 | ## Cosas a tener en cuenta 📚
8 |
9 | Este proyecto consta de dos componentes principales:
10 |
11 | #### Backend 🚀
12 |
13 | El backend del proyecto proporciona la lógica y funcionalidad del lado del servidor, incluyendo una implementación de inicio de sesión. Este inicio de sesión utiliza tokens y cookies para la autenticación. Los estudiantes pueden encontrar más información y acceder al código del backend en el siguiente enlace:
14 |
15 | - [Backend](./backend/)
16 |
17 | #### Frontend 🚀
18 |
19 | El frontend del proyecto es la interfaz de usuario con la que interactúan los usuarios finales, incluyendo la interfaz de inicio de sesión que se conecta al backend. Los estudiantes pueden acceder al código del frontend y explorar su implementación en el siguiente enlace:
20 |
21 | - [Frontend](./frontend)
22 |
23 | ⌨️ with ❤️ by [@camjasaez](https://github.com/camjasaez)
--------------------------------------------------------------------------------
/backend/src/middlewares/authentication.middleware.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import jwt from "jsonwebtoken";
4 | import { ACCESS_JWT_SECRET } from "../config/configEnv.js";
5 | import { respondError } from "../utils/resHandler.js";
6 | import { handleError } from "../utils/errorHandler.js";
7 |
8 | /**
9 | * Verifica el token de acceso
10 | * @param {Object} req - Objeto de petición
11 | * @param {Object} res - Objeto de respuesta
12 | * @param {Function} next - Función para continuar con la siguiente función
13 | */
14 | const verifyJWT = (req, res, next) => {
15 | try {
16 | const authHeader = req.headers.authorization || req.headers.Authorization;
17 |
18 | if (!authHeader?.startsWith("Bearer ")) {
19 | return respondError(
20 | req,
21 | res,
22 | 401,
23 | "No autorizado",
24 | "No hay token valido",
25 | );
26 | }
27 |
28 | const token = authHeader.split(" ")[1];
29 |
30 | jwt.verify(token, ACCESS_JWT_SECRET, (err, decoded) => {
31 | if (err) return respondError(req, res, 403, "No autorizado", err.message);
32 | req.email = decoded.email;
33 | req.roles = decoded.roles;
34 | next();
35 | });
36 | } catch (error) {
37 | handleError(error, "authentication.middleware -> verifyToken");
38 | }
39 | };
40 |
41 | export default verifyJWT;
42 |
--------------------------------------------------------------------------------
/backend/src/models/user.model.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // Import the 'mongoose' module to create the database connection
3 | import mongoose from "mongoose";
4 | import bcrypt from "bcryptjs";
5 |
6 | // Create the 'users' collection schema
7 | const userSchema = new mongoose.Schema(
8 | {
9 | username: {
10 | type: String,
11 | required: true,
12 | },
13 | rut: {
14 | type: String,
15 | required: true,
16 | unique: true,
17 | },
18 | password: {
19 | type: String,
20 | required: true,
21 | },
22 | email: {
23 | type: String,
24 | required: true,
25 | unique: true,
26 | },
27 | roles: [
28 | {
29 | type: mongoose.Schema.Types.ObjectId,
30 | ref: "Role",
31 | },
32 | ],
33 | },
34 | {
35 | versionKey: false,
36 | },
37 | );
38 |
39 | /** Encrypts the user's password */
40 | userSchema.statics.encryptPassword = async (password) => {
41 | const salt = await bcrypt.genSalt(10);
42 | return await bcrypt.hash(password, salt);
43 | };
44 |
45 | /** Compares the user's password */
46 | userSchema.statics.comparePassword = async (password, receivedPassword) => {
47 | return await bcrypt.compare(password, receivedPassword);
48 | };
49 |
50 | /** 'User' data model */
51 | const User = mongoose.model("User", userSchema);
52 |
53 | // Export the 'User' data model
54 | export default User;
55 |
--------------------------------------------------------------------------------
/frontend/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/backend/src/config/initialSetup.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // Importa el modelo de datos 'Role'
3 | import Role from "../models/role.model.js";
4 | import User from "../models/user.model.js";
5 |
6 | /**
7 | * Crea los roles por defecto en la base de datos.
8 | * @async
9 | * @function createRoles
10 | * @returns {Promise}
11 | */
12 | async function createRoles() {
13 | try {
14 | // Busca todos los roles en la base de datos
15 | const count = await Role.estimatedDocumentCount();
16 | // Si no hay roles en la base de datos los crea
17 | if (count > 0) return;
18 |
19 | await Promise.all([
20 | new Role({ name: "user" }).save(),
21 | new Role({ name: "admin" }).save(),
22 | ]);
23 | console.log("* => Roles creados exitosamente");
24 | } catch (error) {
25 | console.error(error);
26 | }
27 | }
28 |
29 | /**
30 | * Crea los usuarios por defecto en la base de datos.
31 | * @async
32 | * @function createUsers
33 | * @returns {Promise}
34 | */
35 | async function createUsers() {
36 | try {
37 | const count = await User.estimatedDocumentCount();
38 | if (count > 0) return;
39 |
40 | const admin = await Role.findOne({ name: "admin" });
41 | const user = await Role.findOne({ name: "user" });
42 |
43 | await Promise.all([
44 | new User({
45 | username: "user",
46 | email: "user@email.com",
47 | rut: "12345678-9",
48 | password: await User.encryptPassword("user123"),
49 | roles: user._id,
50 | }).save(),
51 | new User({
52 | username: "admin",
53 | email: "admin@email.com",
54 | rut: "12345678-0",
55 | password: await User.encryptPassword("admin123"),
56 | roles: admin._id,
57 | }).save(),
58 | ]);
59 | console.log("* => Users creados exitosamente");
60 | } catch (error) {
61 | console.error(error);
62 | }
63 | }
64 |
65 | export { createRoles, createUsers };
66 |
--------------------------------------------------------------------------------
/backend/src/utils/resHandler.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /**
3 | * Envía una respuesta exitosa estandarizada.
4 | * @function respondSuccess
5 | * @param {Object} req - Objeto de petición
6 | * @param {Object} res - Objeto de respuesta
7 | * @param {Number} statusCode - Código de estado para la operación
8 | * @param {Object} data - Objeto que contiene los datos a enviar
9 | * @returns {JSON} - Objeto de respuesta JSON con el estado "Success" y los datos proporcionados
10 | */
11 | function respondSuccess(req, res, statusCode = 200, data = {}) {
12 | return res.status(statusCode).json({
13 | state: "Success",
14 | data,
15 | });
16 | }
17 |
18 | /**
19 | * Envía una respuesta de error estandarizada.
20 | * @function respondError
21 | * @param {Object} req - El objeto de petición
22 | * @param {Object} res - El objeto de respuesta
23 | * @param {Number} statusCode - Código de estado para la operación
24 | * @param {String} message - La descripción del motivo del error
25 | * @param {Object} details - Información adicional sobre el error
26 | * @returns {JSON} - El objeto de respuesta JSON con el estado "Error", el mensaje de error y los detalles proporcionados
27 | */
28 | function respondError(
29 | req,
30 | res,
31 | statusCode = 500,
32 | message = "Couldnt process the request",
33 | details = {},
34 | ) {
35 | return res.status(statusCode).json({
36 | state: "Error",
37 | message,
38 | details,
39 | });
40 | }
41 |
42 | /**
43 | * Envía una respuesta de error interno estandarizada.
44 | * @function respondInternalError
45 | * @param {Object} req - El objeto de petición
46 | * @param {Object} res - El objeto de respuesta
47 | * @param {Number} statusCode - El código de estado para la operación
48 | * @param {String} message - La descripción del motivo del error
49 | * @returns {JSON} - El objeto de respuesta JSON con el estado "Error" y el mensaje de error proporcionados
50 | */
51 | function respondInternalError(
52 | req,
53 | res,
54 | statusCode = 500,
55 | message = "Couldnt process the request",
56 | ) {
57 | return res.status(statusCode).json({
58 | state: "Error",
59 | message,
60 | });
61 | }
62 |
63 | export { respondSuccess, respondError, respondInternalError };
64 |
--------------------------------------------------------------------------------
/backend/src/server.js:
--------------------------------------------------------------------------------
1 | // Importa el archivo 'configEnv.js' para cargar las variables de entorno
2 | import { PORT, HOST } from "./config/configEnv.js";
3 | // Importa el módulo 'cors' para agregar los cors
4 | import cors from "cors";
5 | // Importa el módulo 'express' para crear la aplicacion web
6 | import express, { urlencoded, json } from "express";
7 | // Importamos morgan para ver las peticiones que se hacen al servidor
8 | import morgan from "morgan";
9 | // Importa el módulo 'cookie-parser' para manejar las cookies
10 | import cookieParser from "cookie-parser";
11 | /** El enrutador principal */
12 | import indexRoutes from "./routes/index.routes.js";
13 | // Importa el archivo 'configDB.js' para crear la conexión a la base de datos
14 | import { setupDB } from "./config/configDB.js";
15 | // Importa el handler de errores
16 | import { handleFatalError, handleError } from "./utils/errorHandler.js";
17 | import { createRoles, createUsers } from "./config/initialSetup.js";
18 |
19 | /**
20 | * Inicia el servidor web
21 | */
22 | async function setupServer() {
23 | try {
24 | /** Instancia de la aplicacion */
25 | const server = express();
26 | server.disable("x-powered-by");
27 | // Agregamos los cors
28 | server.use(cors({ credentials: true, origin: true }));
29 | // Agrega el middleware para el manejo de datos en formato URL
30 | server.use(urlencoded({ extended: true }));
31 | // Agrega el middleware para el manejo de datos en formato JSON
32 | server.use(json());
33 | // Agregamos el middleware para el manejo de cookies
34 | server.use(cookieParser());
35 | // Agregamos morgan para ver las peticiones que se hacen al servidor
36 | server.use(morgan("dev"));
37 | // Agrega el enrutador principal al servidor
38 | server.use("/api", indexRoutes);
39 |
40 | // Inicia el servidor en el puerto especificado
41 | server.listen(PORT, () => {
42 | console.log(`=> Servidor corriendo en ${HOST}:${PORT}/api`);
43 | });
44 | } catch (err) {
45 | handleError(err, "/server.js -> setupServer");
46 | }
47 | }
48 |
49 | /**
50 | * Inicia la API
51 | */
52 | async function setupAPI() {
53 | try {
54 | // Inicia la conexión a la base de datos
55 | await setupDB();
56 | // Inicia el servidor web
57 | await setupServer();
58 | // Inicia la creación de los roles
59 | await createRoles();
60 | // Inicia la creación del usuario admin y user
61 | await createUsers();
62 | } catch (err) {
63 | handleFatalError(err, "/server.js -> setupAPI");
64 | }
65 | }
66 |
67 | // Inicia la API
68 | setupAPI()
69 | .then(() => console.log("=> API Iniciada exitosamente"))
70 | .catch((err) => handleFatalError(err, "/server.js -> setupAPI"));
71 |
--------------------------------------------------------------------------------
/backend/src/controllers/auth.controller.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import { respondSuccess, respondError } from "../utils/resHandler.js";
4 | import { handleError } from "../utils/errorHandler.js";
5 |
6 | /** Servicios de autenticación */
7 | import AuthService from "../services/auth.service.js";
8 | import { authLoginBodySchema } from "../schema/auth.schema.js";
9 |
10 | /**
11 | * Inicia sesión con un usuario.
12 | * @async
13 | * @function login
14 | * @param {Object} req - Objeto de petición
15 | * @param {Object} res - Objeto de respuesta
16 | */
17 | async function login(req, res) {
18 | try {
19 | const { body } = req;
20 | const { error: bodyError } = authLoginBodySchema.validate(body);
21 | if (bodyError) return respondError(req, res, 400, bodyError.message);
22 |
23 | const [accessToken, refreshToken, errorToken] =
24 | await AuthService.login(body);
25 |
26 | if (errorToken) return respondError(req, res, 400, errorToken);
27 |
28 | // * Existen mas opciones de seguirdad para las cookies *//
29 | res.cookie("jwt", refreshToken, {
30 | httpOnly: true,
31 | maxAge: 7 * 24 * 60 * 60 * 1000, // 7 días
32 | });
33 |
34 | respondSuccess(req, res, 200, { accessToken });
35 | } catch (error) {
36 | handleError(error, "auth.controller -> login");
37 | respondError(req, res, 400, error.message);
38 | }
39 | }
40 |
41 | /**
42 | * @name logout
43 | * @description Cierra la sesión del usuario
44 | * @param {Object} req - Objeto de petición
45 | * @param {Object} res - Objeto de respuesta
46 | * @returns
47 | */
48 | async function logout(req, res) {
49 | try {
50 | const cookies = req.cookies;
51 | if (!cookies?.jwt) return respondError(req, res, 400, "No hay token");
52 | res.clearCookie("jwt", { httpOnly: true });
53 | respondSuccess(req, res, 200, { message: "Sesión cerrada correctamente" });
54 | } catch (error) {
55 | handleError(error, "auth.controller -> logout");
56 | respondError(req, res, 400, error.message);
57 | }
58 | }
59 |
60 | /**
61 | * @name refresh
62 | * @description Refresca el token de acceso
63 | * @param {Object} req - Objeto de petición
64 | * @param {Object} res - Objeto de respuesta
65 | */
66 | async function refresh(req, res) {
67 | try {
68 | const cookies = req.cookies;
69 | if (!cookies?.jwt) return respondError(req, res, 400, "No hay token");
70 |
71 | const [accessToken, errorToken] = await AuthService.refresh(cookies);
72 |
73 | if (errorToken) return respondError(req, res, 400, errorToken);
74 |
75 | respondSuccess(req, res, 200, { accessToken });
76 | } catch (error) {
77 | handleError(error, "auth.controller -> refresh");
78 | respondError(req, res, 400, error.message);
79 | }
80 | }
81 |
82 | export default {
83 | login,
84 | logout,
85 | refresh,
86 | };
87 |
--------------------------------------------------------------------------------
/backend/src/schema/user.schema.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import Joi from "joi";
4 | import ROLES from "../constants/roles.constants.js";
5 | /**
6 | * Esquema de validación para el cuerpo de la solicitud de usuario.
7 | * @constant {Object}
8 | */
9 | const userBodySchema = Joi.object({
10 | username: Joi.string().required().messages({
11 | "string.empty": "El nombre de usuario no puede estar vacío.",
12 | "any.required": "El nombre de usuario es obligatorio.",
13 | "string.base": "El nombre de usuario debe ser de tipo string.",
14 | }),
15 | rut: Joi.string().required().min(9).max(10)
16 | .pattern(/^[0-9]+[-|‐]{1}[0-9kK]{1}$/).messages({
17 | "string.empty": "El rut no puede estar vacío.",
18 | "any.required": "El rut es obligatorio.",
19 | "string.base": "El rut debe ser de tipo string.",
20 | "string.min": "El rut debe tener al menos 9 caracteres.",
21 | "string.max": "El rut debe tener al menos 10 caracteres.",
22 | "string.pattern.base": "El rut tiene el formato XXXXXXXX-X, ejemplo: 12345678-9.",
23 | }),
24 | password: Joi.string().required().min(5).messages({
25 | "string.empty": "La contraseña no puede estar vacía.",
26 | "any.required": "La contraseña es obligatoria.",
27 | "string.base": "La contraseña debe ser de tipo string.",
28 | "string.min": "La contraseña debe tener al menos 5 caracteres.",
29 | }),
30 | email: Joi.string().email().required().messages({
31 | "string.empty": "El email no puede estar vacío.",
32 | "any.required": "El email es obligatorio.",
33 | "string.base": "El email debe ser de tipo string.",
34 | "string.email": "El email debe tener un formato válido.",
35 | }),
36 | roles: Joi.array()
37 | .items(Joi.string().valid(...ROLES))
38 | .required()
39 | .messages({
40 | "array.base": "El rol debe ser de tipo array.",
41 | "any.required": "El rol es obligatorio.",
42 | "string.base": "El rol debe ser de tipo string.",
43 | "any.only": "El rol proporcionado no es válido.",
44 | }),
45 | newPassword: Joi.string().min(5).messages({
46 | "string.empty": "La contraseña no puede estar vacía.",
47 | "string.base": "La contraseña debe ser de tipo string.",
48 | "string.min": "La contraseña debe tener al menos 5 caracteres.",
49 | }),
50 | }).messages({
51 | "object.unknown": "No se permiten propiedades adicionales.",
52 | });
53 |
54 | /**
55 | * Esquema de validación para el id de usuario.
56 | * @constant {Object}
57 | */
58 | const userIdSchema = Joi.object({
59 | id: Joi.string()
60 | .required()
61 | .pattern(/^(?:[0-9a-fA-F]{24}|[0-9a-fA-F]{12})$/)
62 | .messages({
63 | "string.empty": "El id no puede estar vacío.",
64 | "any.required": "El id es obligatorio.",
65 | "string.base": "El id debe ser de tipo string.",
66 | "string.pattern.base": "El id proporcionado no es un ObjectId válido.",
67 | }),
68 | });
69 |
70 | export { userBodySchema, userIdSchema };
71 |
--------------------------------------------------------------------------------
/backend/src/services/auth.service.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | /** Modelo de datos 'User' */
4 | import User from "../models/user.model.js";
5 | /** Modulo 'jsonwebtoken' para crear tokens */
6 | import jwt from "jsonwebtoken";
7 |
8 | import { ACCESS_JWT_SECRET, REFRESH_JWT_SECRET } from "../config/configEnv.js";
9 |
10 | import { handleError } from "../utils/errorHandler.js";
11 |
12 | /**
13 | * Inicia sesión con un usuario.
14 | * @async
15 | * @function login
16 | * @param {Object} user - Objeto de usuario
17 | */
18 | async function login(user) {
19 | try {
20 | const { email, password } = user;
21 |
22 | const userFound = await User.findOne({ email: email })
23 | .populate("roles")
24 | .exec();
25 | if (!userFound) {
26 | return [null, null, "El usuario y/o contraseña son incorrectos"];
27 | }
28 |
29 | const matchPassword = await User.comparePassword(
30 | password,
31 | userFound.password,
32 | );
33 |
34 | if (!matchPassword) {
35 | return [null, null, "El usuario y/o contraseña son incorrectos"];
36 | }
37 |
38 | const accessToken = jwt.sign(
39 | { email: userFound.email, roles: userFound.roles },
40 | ACCESS_JWT_SECRET,
41 | {
42 | expiresIn: "1d",
43 | },
44 | );
45 |
46 | const refreshToken = jwt.sign(
47 | { email: userFound.email },
48 | REFRESH_JWT_SECRET,
49 | {
50 | expiresIn: "7d", // 7 días
51 | },
52 | );
53 |
54 | return [accessToken, refreshToken, null];
55 | } catch (error) {
56 | handleError(error, "auth.service -> signIn");
57 | }
58 | }
59 |
60 | /**
61 | * Refresca el token de acceso
62 | * @async
63 | * @function refresh
64 | * @param {Object} cookies - Objeto de cookies
65 | */
66 | async function refresh(cookies) {
67 | try {
68 | if (!cookies.jwt) return [null, "No hay autorización"];
69 | const refreshToken = cookies.jwt;
70 |
71 | const accessToken = await jwt.verify(
72 | refreshToken,
73 | REFRESH_JWT_SECRET,
74 | async (err, user) => {
75 | if (err) return [null, "La sesion a caducado, vuelva a iniciar sesion"];
76 |
77 | const userFound = await User.findOne({
78 | email: user.email,
79 | })
80 | .populate("roles")
81 | .exec();
82 |
83 | if (!userFound) return [null, "No usuario no autorizado"];
84 |
85 | const accessToken = jwt.sign(
86 | { email: userFound.email, roles: userFound.roles },
87 | ACCESS_JWT_SECRET,
88 | {
89 | expiresIn: "1d",
90 | },
91 | );
92 |
93 | return [accessToken, null];
94 | },
95 | );
96 |
97 | return accessToken;
98 | } catch (error) {
99 | handleError(error, "auth.service -> refresh");
100 | }
101 | }
102 |
103 | export default { login, refresh };
104 |
--------------------------------------------------------------------------------
/backend/.gitignore:
--------------------------------------------------------------------------------
1 | # Project
2 | .env
3 | #Node
4 | node_modules
5 |
6 | # Logs
7 | logs
8 | *.log
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 | lerna-debug.log*
13 | .pnpm-debug.log*
14 |
15 | # Diagnostic reports (https://nodejs.org/api/report.html)
16 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
17 |
18 | # Runtime data
19 | pids
20 | *.pid
21 | *.seed
22 | *.pid.lock
23 |
24 | # Directory for instrumented libs generated by jscoverage/JSCover
25 | lib-cov
26 |
27 | # Coverage directory used by tools like istanbul
28 | coverage
29 | *.lcov
30 |
31 | # nyc test coverage
32 | .nyc_output
33 |
34 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
35 | .grunt
36 |
37 | # Bower dependency directory (https://bower.io/)
38 | bower_components
39 |
40 | # node-waf configuration
41 | .lock-wscript
42 |
43 | # Compiled binary addons (https://nodejs.org/api/addons.html)
44 | build/Release
45 |
46 | # Dependency directories
47 | backend/node_modules/
48 | backend/upload/
49 | frontend/node_modules/
50 | jspm_packages/
51 |
52 | # Snowpack dependency directory (https://snowpack.dev/)
53 | web_modules/
54 |
55 | # TypeScript cache
56 | *.tsbuildinfo
57 |
58 | # Optional npm cache directory
59 | .npm
60 |
61 | # Optional eslint cache
62 | .eslintcache
63 |
64 | # Optional stylelint cache
65 | .stylelintcache
66 |
67 | # Microbundle cache
68 | .rpt2_cache/
69 | .rts2_cache_cjs/
70 | .rts2_cache_es/
71 | .rts2_cache_umd/
72 |
73 | # Optional REPL history
74 | .node_repl_history
75 |
76 | # Output of 'npm pack'
77 | *.tgz
78 |
79 | # Yarn Integrity file
80 | .yarn-integrity
81 |
82 | # dotenv environment variable files
83 | backend/.env
84 | frontend/.env
85 | .env.development.local
86 | .env.test.local
87 | .env.production.local
88 | .env.local
89 |
90 | # parcel-bundler cache (https://parceljs.org/)
91 | .cache
92 | .parcel-cache
93 |
94 | # Next.js build output
95 | .next
96 | out
97 |
98 | # Nuxt.js build / generate output
99 | .nuxt
100 | dist
101 |
102 | # Gatsby files
103 | .cache/
104 | # Comment in the public line in if your project uses Gatsby and not Next.js
105 | # https://nextjs.org/blog/next-9-1#public-directory-support
106 | # public
107 |
108 | # vuepress build output
109 | .vuepress/dist
110 |
111 | # vuepress v2.x temp and cache directory
112 | .temp
113 |
114 | # Docusaurus cache and generated files
115 | .docusaurus
116 |
117 | # Serverless directories
118 | .serverless/
119 |
120 | # FuseBox cache
121 | .fusebox/
122 |
123 | # DynamoDB Local files
124 | .dynamodb/
125 |
126 | # TernJS port file
127 | .tern-port
128 |
129 | # Stores VSCode versions used for testing VSCode extensions
130 | .vscode-test
131 |
132 | # yarn v2
133 | .yarn/cache
134 | .yarn/unplugged
135 | .yarn/build-state.yml
136 | .yarn/install-state.gz
137 | .pnp.*
138 |
139 | # JetBrains
140 | .idea/
141 |
142 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
143 |
144 | # testing
145 | frontend/coverage
146 |
147 | # next.js
148 | frontend/.next/
149 | frontend/out/
150 |
151 | # production
152 | frontend/build
153 |
154 | # misc
155 | frontend/.DS_Store
156 | frontend/*.pem
157 |
158 | # local env files
159 | frontend/.env*.local
160 |
161 | # vercel
162 | frontend/.vercel
163 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Project
2 | .env
3 | #Node
4 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
5 |
6 | # dependencies
7 | /node_modules
8 | /.pnp
9 | .pnp.js
10 |
11 | # testing
12 | /coverage
13 |
14 | # next.js
15 | /.next/
16 | /out/
17 |
18 | # production
19 | /build
20 |
21 | # misc
22 | .DS_Store
23 | *.pem
24 |
25 | # debug
26 | npm-debug.log*
27 | yarn-debug.log*
28 | yarn-error.log*
29 |
30 | # local env files
31 | .env*.local
32 |
33 | # vercel
34 | .vercel
35 |
36 | # typescript
37 | *.tsbuildinfo
38 | next-env.d.ts
39 |
40 |
41 | # Logs
42 | logs
43 | *.log
44 | lerna-debug.log*
45 | .pnpm-debug.log*
46 |
47 | # Diagnostic reports (https://nodejs.org/api/report.html)
48 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
49 |
50 | # Runtime data
51 | pids
52 | *.pid
53 | *.seed
54 | *.pid.lock
55 |
56 | # Directory for instrumented libs generated by jscoverage/JSCover
57 | lib-cov
58 |
59 | # Coverage directory used by tools like istanbul
60 | coverage
61 | *.lcov
62 |
63 | # nyc test coverage
64 | .nyc_output
65 |
66 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
67 | .grunt
68 |
69 | # Bower dependency directory (https://bower.io/)
70 | bower_components
71 |
72 | # node-waf configuration
73 | .lock-wscript
74 |
75 | # Compiled binary addons (https://nodejs.org/api/addons.html)
76 | build/Release
77 |
78 | # Dependency directories
79 | backend/node_modules/
80 | backend/upload/
81 | frontend/node_modules/
82 | jspm_packages/
83 |
84 | # Snowpack dependency directory (https://snowpack.dev/)
85 | web_modules/
86 |
87 |
88 | # Optional npm cache directory
89 | .npm
90 |
91 | # Optional eslint cache
92 | .eslintcache
93 |
94 | # Optional stylelint cache
95 | .stylelintcache
96 |
97 | # Microbundle cache
98 | .rpt2_cache/
99 | .rts2_cache_cjs/
100 | .rts2_cache_es/
101 | .rts2_cache_umd/
102 |
103 | # Optional REPL history
104 | .node_repl_history
105 |
106 | # Output of 'npm pack'
107 | *.tgz
108 |
109 | # Yarn Integrity file
110 | .yarn-integrity
111 |
112 | # dotenv environment variable files
113 | backend/.env
114 | frontend/.env.local
115 | .env.development.local
116 | .env.test.local
117 | .env.production.local
118 | .env.local
119 |
120 | # parcel-bundler cache (https://parceljs.org/)
121 | .cache
122 | .parcel-cache
123 |
124 | # Next.js build output
125 | .next
126 | out
127 |
128 | # Nuxt.js build / generate output
129 | .nuxt
130 | dist
131 |
132 | # Gatsby files
133 | .cache/
134 | # Comment in the public line in if your project uses Gatsby and not Next.js
135 | # https://nextjs.org/blog/next-9-1#public-directory-support
136 | # public
137 |
138 | # vuepress build output
139 | .vuepress/dist
140 |
141 | # vuepress v2.x temp and cache directory
142 | .temp
143 |
144 | # Docusaurus cache and generated files
145 | .docusaurus
146 |
147 | # Serverless directories
148 | .serverless/
149 |
150 | # FuseBox cache
151 | .fusebox/
152 |
153 | # DynamoDB Local files
154 | .dynamodb/
155 |
156 | # TernJS port file
157 | .tern-port
158 |
159 | # Stores VSCode versions used for testing VSCode extensions
160 | .vscode-test
161 |
162 | # yarn v2
163 | .yarn/cache
164 | .yarn/unplugged
165 | .yarn/build-state.yml
166 | .yarn/install-state.gz
167 | .pnp.*
168 |
169 | # JetBrains
170 | .idea/
171 | .idea
172 |
173 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
174 |
175 | # testing
176 | frontend/coverage
177 |
178 | # next.js
179 | frontend/.next/
180 | frontend/out/
181 |
182 | # production
183 | frontend/build
184 |
185 | # misc
186 | frontend/.DS_Store
187 | frontend/*.pem
188 |
189 | # local env files
190 | frontend/.env*.local
191 |
192 | # vercel
193 | frontend/.vercel
194 |
--------------------------------------------------------------------------------
/frontend/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/backend/src/services/user.service.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // Importa el modelo de datos 'User'
3 | import User from "../models/user.model.js";
4 | import Role from "../models/role.model.js";
5 | import { handleError } from "../utils/errorHandler.js";
6 |
7 | /**
8 | * Obtiene todos los usuarios de la base de datos
9 | * @returns {Promise} Promesa con el objeto de los usuarios
10 | */
11 | async function getUsers() {
12 | try {
13 | const users = await User.find()
14 | .select("-password")
15 | .populate("roles")
16 | .exec();
17 | if (!users) return [null, "No hay usuarios"];
18 |
19 | return [users, null];
20 | } catch (error) {
21 | handleError(error, "user.service -> getUsers");
22 | }
23 | }
24 |
25 | /**
26 | * Crea un nuevo usuario en la base de datos
27 | * @param {Object} user Objeto de usuario
28 | * @returns {Promise} Promesa con el objeto de usuario creado
29 | */
30 | async function createUser(user) {
31 | try {
32 | const { username, rut, email, password, roles } = user;
33 |
34 | const userFound = await User.findOne({ email: user.email });
35 | if (userFound) return [null, "El usuario ya existe"];
36 |
37 | const rolesFound = await Role.find({ name: { $in: roles } });
38 | if (rolesFound.length === 0) return [null, "El rol no existe"];
39 | const myRole = rolesFound.map((role) => role._id);
40 |
41 | const newUser = new User({
42 | username,
43 | rut,
44 | email,
45 | password: await User.encryptPassword(password),
46 | roles: myRole,
47 | });
48 | await newUser.save();
49 |
50 | return [newUser, null];
51 | } catch (error) {
52 | handleError(error, "user.service -> createUser");
53 | }
54 | }
55 |
56 | /**
57 | * Obtiene un usuario por su id de la base de datos
58 | * @param {string} Id del usuario
59 | * @returns {Promise} Promesa con el objeto de usuario
60 | */
61 | async function getUserById(id) {
62 | try {
63 | const user = await User.findById({ _id: id })
64 | .select("-password")
65 | .populate("roles")
66 | .exec();
67 |
68 | if (!user) return [null, "El usuario no existe"];
69 |
70 | return [user, null];
71 | } catch (error) {
72 | handleError(error, "user.service -> getUserById");
73 | }
74 | }
75 |
76 | /**
77 | * Actualiza un usuario por su id en la base de datos
78 | * @param {string} id Id del usuario
79 | * @param {Object} user Objeto de usuario
80 | * @returns {Promise} Promesa con el objeto de usuario actualizado
81 | */
82 | async function updateUser(id, user) {
83 | try {
84 | const userFound = await User.findById(id);
85 | if (!userFound) return [null, "El usuario no existe"];
86 |
87 | const { username, email, rut, password, newPassword, roles } = user;
88 |
89 | const matchPassword = await User.comparePassword(
90 | password,
91 | userFound.password,
92 | );
93 |
94 | if (!matchPassword) {
95 | return [null, "La contraseña no coincide"];
96 | }
97 |
98 | const rolesFound = await Role.find({ name: { $in: roles } });
99 | if (rolesFound.length === 0) return [null, "El rol no existe"];
100 |
101 | const myRole = rolesFound.map((role) => role._id);
102 |
103 | const userUpdated = await User.findByIdAndUpdate(
104 | id,
105 | {
106 | username,
107 | email,
108 | rut,
109 | password: await User.encryptPassword(newPassword || password),
110 | roles: myRole,
111 | },
112 | { new: true },
113 | );
114 |
115 | return [userUpdated, null];
116 | } catch (error) {
117 | handleError(error, "user.service -> updateUser");
118 | }
119 | }
120 |
121 | /**
122 | * Elimina un usuario por su id de la base de datos
123 | * @param {string} Id del usuario
124 | * @returns {Promise} Promesa con el objeto de usuario eliminado
125 | */
126 | async function deleteUser(id) {
127 | try {
128 | return await User.findByIdAndDelete(id);
129 | } catch (error) {
130 | handleError(error, "user.service -> deleteUser");
131 | }
132 | }
133 |
134 | export default {
135 | getUsers,
136 | createUser,
137 | getUserById,
138 | updateUser,
139 | deleteUser,
140 | };
141 |
--------------------------------------------------------------------------------
/backend/README.md:
--------------------------------------------------------------------------------
1 | ## Backend Template para proyecto ingeniería de software
2 |
3 | ### Instrucciones de instalacion
4 |
5 | - Clonar el repositorio
6 | - Instalar dependencias con `npm install`
7 | - Crear archivo `.env` con las variables de entorno, en la carpeta `/config`
8 | - Sigue la estructura del archivo `.env.example`
9 | - Agrega la variable `PORT` con el puerto en el que quieres que corra el servidor
10 | - Agrega la variable `HOST` con la URL del servidor
11 | - Agrega la variable `DB_URL` con la URI de la base de datos
12 | - Agrega la variable `ACCESS_JWT_SECRET` con la clave secreta para crear los tokens de autenticacion
13 | - Agrega la variable `REFRESH_JWT_SECRET` con la clave secreta para crear los tokens de refresco
14 | - Correr el servidor con `npm start` o `npm run dev`.
15 |
16 | ### Estructura de carpetas
17 |
18 | ```bash
19 |
20 | ├── NombreProyecto
21 | │ ├── node_modules
22 | │ ├── src
23 | │ │ ├── config
24 | │ │ │ ├── .env.example
25 | │ │ │ ├── initialSetup.js
26 | │ │ │ ├── configDB.js
27 | │ │ │ └── configEnv.js
28 | │ │ ├── constants
29 | │ │ │ ├── roles.constants.js
30 | │ │ ├── controllers
31 | │ │ │ ├── auth.controller.js
32 | │ │ │ └── user.controller.js
33 | │ │ ├── middlewares
34 | │ │ │ ├── authentication.middleware.js
35 | │ │ │ └── authorization.middleware.js
36 | │ │ ├── models
37 | │ │ │ ├── auth.model.js
38 | │ │ │ └── user.model.js
39 | │ │ ├── routes
40 | │ │ │ ├── auth.route.js
41 | │ │ │ ├── user.route.js
42 | │ │ │ └── index.routes.js
43 | │ │ ├── services
44 | │ │ │ ├── auth.service.js
45 | │ │ │ └── user.service.js
46 | │ │ ├── schemas
47 | │ │ │ ├── user.schema.js
48 | │ │ │ └── auth.schema.js
49 | │ │ ├── utils
50 | │ │ │ ├── resHandler.js
51 | │ │ │ └── errorHandler.js
52 | │ │ └── server.js
53 | │ ├── .eslintrc.json
54 | │ ├── .prettierrc.json
55 | │ ├── .gitignore
56 | └── └── package.json
57 | ```
58 |
59 | ## Arquitectura de la API
60 |
61 | 
62 |
63 | ## Instrucciones de uso
64 |
65 | - Una vez instaladas las dependencias y configuradas las variables de entorno, puedes correr el servidor con `npm start`
66 | - Recuerda que **debes utilizar** Postman o Insomnia para hacer las peticiones a la API
67 | - De manera automatica se creara un usuario administrador y user, con los siguientes datos:
68 | - **Administrador**
69 | - `email: admin@email.com`
70 | - `password: admin123`
71 | - **User**
72 | - `email: user@email.com`
73 | - `password: user123`
74 | - Tambien, de manera automatica se crean dos roles principales en la base de datos:
75 | - `admin`
76 | - `user`
77 | - Se debe **autenticar con el usuario admin** para poder usar el endpoint de usuarios ( Pueden modificar esto en el archivo de rutas )
78 | - Para la autenticacion, se debe enviar un objeto JSON con el email y constraseña al endpoint `/api/auth/login`
79 | - Ejemplo:
80 | ```json
81 | {
82 | "email": "admin@email.com",
83 | "password": "admin123"
84 | }
85 | ```
86 | - Devuelve un token que se **debe enviar en el header** de las peticiones que requieran autenticacion, con el nombre `Authorization` y el valor `Bearer `
87 | - El token tiene una duracion de 24 horas, despues de ese tiempo, se puede refrescar el token con el endpoint `/api/auth/refresh`
88 | - El token de refresco, tiene una duracion de 7 dias, despues de ese tiempo, se debe volver a autenticar
89 |
90 | ## Consideraciones
91 |
92 | - El manejo de tokens, esta simplificado para hacerlo mas facil de entender
93 | - La abstracion de la autenticacion, se completará con el frontend
94 |
95 | ## Librerias utilizadas
96 |
97 | - [Node](https://nodejs.org/es/): Entorno de ejecucion de JS
98 | - [Express](https://expressjs.com/es/): Framework para crear servidores web
99 | - [Mongoose](https://mongoosejs.com/): Libreria para conectar a MongoDB
100 | - [JsonWebToken](https://www.npmjs.com/package/jsonwebtoken): Libreria para crear tokens de autenticacion
101 | - [Dotenv](https://www.npmjs.com/package/dotenv): Libreria para manejar variables de entorno
102 | - [Cors](https://www.npmjs.com/package/cors): Libreria para manejar el CORS
103 | - [Joi](https://www.npmjs.com/package/joi): Libreria para manejar validaciones
104 | - [Morgan](https://www.npmjs.com/package/morgan): Libreria para manejar logs
105 |
106 | [Volver al inicio](../README.md)
107 |
108 |
--------------------------------------------------------------------------------
/backend/src/controllers/user.controller.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import { respondSuccess, respondError } from "../utils/resHandler.js";
4 | import UserService from "../services/user.service.js";
5 | import { userBodySchema, userIdSchema } from "../schema/user.schema.js";
6 | import { handleError } from "../utils/errorHandler.js";
7 |
8 | /**
9 | * Obtiene todos los usuarios
10 | * @param {Object} req - Objeto de petición
11 | * @param {Object} res - Objeto de respuesta
12 | */
13 | async function getUsers(req, res) {
14 | try {
15 | const [usuarios, errorUsuarios] = await UserService.getUsers();
16 | if (errorUsuarios) return respondError(req, res, 404, errorUsuarios);
17 |
18 | usuarios.length === 0
19 | ? respondSuccess(req, res, 204)
20 | : respondSuccess(req, res, 200, usuarios);
21 | } catch (error) {
22 | handleError(error, "user.controller -> getUsers");
23 | respondError(req, res, 400, error.message);
24 | }
25 | }
26 |
27 | /**
28 | * Crea un nuevo usuario
29 | * @param {Object} req - Objeto de petición
30 | * @param {Object} res - Objeto de respuesta
31 | */
32 | async function createUser(req, res) {
33 | try {
34 | const { body } = req;
35 | const { error: bodyError } = userBodySchema.validate(body);
36 | if (bodyError) return respondError(req, res, 400, bodyError.message);
37 |
38 | const [newUser, userError] = await UserService.createUser(body);
39 |
40 | if (userError) return respondError(req, res, 400, userError);
41 | if (!newUser) {
42 | return respondError(req, res, 400, "No se creo el usuario");
43 | }
44 |
45 | respondSuccess(req, res, 201, newUser);
46 | } catch (error) {
47 | handleError(error, "user.controller -> createUser");
48 | respondError(req, res, 500, "No se creo el usuario");
49 | }
50 | }
51 |
52 | /**
53 | * Obtiene un usuario por su id
54 | * @param {Object} req - Objeto de petición
55 | * @param {Object} res - Objeto de respuesta
56 | */
57 | async function getUserById(req, res) {
58 | try {
59 | const { params } = req;
60 | const { error: paramsError } = userIdSchema.validate(params);
61 | if (paramsError) return respondError(req, res, 400, paramsError.message);
62 |
63 | const [user, errorUser] = await UserService.getUserById(params.id);
64 |
65 | if (errorUser) return respondError(req, res, 404, errorUser);
66 |
67 | respondSuccess(req, res, 200, user);
68 | } catch (error) {
69 | handleError(error, "user.controller -> getUserById");
70 | respondError(req, res, 500, "No se pudo obtener el usuario");
71 | }
72 | }
73 |
74 | /**
75 | * Actualiza un usuario por su id
76 | * @param {Object} req - Objeto de petición
77 | * @param {Object} res - Objeto de respuesta
78 | */
79 | async function updateUser(req, res) {
80 | try {
81 | const { params, body } = req;
82 | const { error: paramsError } = userIdSchema.validate(params);
83 | if (paramsError) return respondError(req, res, 400, paramsError.message);
84 |
85 | const { error: bodyError } = userBodySchema.validate(body);
86 | if (bodyError) return respondError(req, res, 400, bodyError.message);
87 |
88 | const [user, userError] = await UserService.updateUser(params.id, body);
89 |
90 | if (userError) return respondError(req, res, 400, userError);
91 |
92 | respondSuccess(req, res, 200, user);
93 | } catch (error) {
94 | handleError(error, "user.controller -> updateUser");
95 | respondError(req, res, 500, "No se pudo actualizar el usuario");
96 | }
97 | }
98 |
99 | /**
100 | * Elimina un usuario por su id
101 | * @param {Object} req - Objeto de petición
102 | * @param {Object} res - Objeto de respuesta
103 | */
104 | async function deleteUser(req, res) {
105 | try {
106 | const { params } = req;
107 | const { error: paramsError } = userIdSchema.validate(params);
108 | if (paramsError) return respondError(req, res, 400, paramsError.message);
109 |
110 | const user = await UserService.deleteUser(params.id);
111 | !user
112 | ? respondError(
113 | req,
114 | res,
115 | 404,
116 | "No se encontro el usuario solicitado",
117 | "Verifique el id ingresado",
118 | )
119 | : respondSuccess(req, res, 200, user);
120 | } catch (error) {
121 | handleError(error, "user.controller -> deleteUser");
122 | respondError(req, res, 500, "No se pudo eliminar el usuario");
123 | }
124 | }
125 |
126 | export default {
127 | getUsers,
128 | createUser,
129 | getUserById,
130 | updateUser,
131 | deleteUser,
132 | };
133 |
--------------------------------------------------------------------------------
/backend/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "api-node",
3 | "version": "1.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "api-node",
9 | "version": "1.0.0",
10 | "license": "MIT",
11 | "dependencies": {
12 | "bcryptjs": "2.4.3",
13 | "cookie-parser": "1.4.6",
14 | "cors": "2.8.5",
15 | "dotenv": "^16.4.4",
16 | "express": "4.18.2",
17 | "joi": "17.10.2",
18 | "jsonwebtoken": "9.0.2",
19 | "mongoose": "^8.1.0",
20 | "morgan": "1.10.0"
21 | },
22 | "devDependencies": {
23 | "eslint": "^8.56.0",
24 | "eslint-config-google": "0.14.0",
25 | "jsdoc": "4.0.2",
26 | "nodemon": "^3.0.3",
27 | "prettier": "^3.2.5"
28 | }
29 | },
30 | "node_modules/@aashutoshrathi/word-wrap": {
31 | "version": "1.2.6",
32 | "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
33 | "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
34 | "dev": true,
35 | "engines": {
36 | "node": ">=0.10.0"
37 | }
38 | },
39 | "node_modules/@babel/parser": {
40 | "version": "7.22.16",
41 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
42 | "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==",
43 | "dev": true,
44 | "bin": {
45 | "parser": "bin/babel-parser.js"
46 | },
47 | "engines": {
48 | "node": ">=6.0.0"
49 | }
50 | },
51 | "node_modules/@eslint-community/eslint-utils": {
52 | "version": "4.4.0",
53 | "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
54 | "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
55 | "dev": true,
56 | "dependencies": {
57 | "eslint-visitor-keys": "^3.3.0"
58 | },
59 | "engines": {
60 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
61 | },
62 | "peerDependencies": {
63 | "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
64 | }
65 | },
66 | "node_modules/@eslint-community/regexpp": {
67 | "version": "4.8.1",
68 | "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.1.tgz",
69 | "integrity": "sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==",
70 | "dev": true,
71 | "engines": {
72 | "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
73 | }
74 | },
75 | "node_modules/@eslint/eslintrc": {
76 | "version": "2.1.4",
77 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
78 | "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
79 | "dev": true,
80 | "dependencies": {
81 | "ajv": "^6.12.4",
82 | "debug": "^4.3.2",
83 | "espree": "^9.6.0",
84 | "globals": "^13.19.0",
85 | "ignore": "^5.2.0",
86 | "import-fresh": "^3.2.1",
87 | "js-yaml": "^4.1.0",
88 | "minimatch": "^3.1.2",
89 | "strip-json-comments": "^3.1.1"
90 | },
91 | "engines": {
92 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
93 | },
94 | "funding": {
95 | "url": "https://opencollective.com/eslint"
96 | }
97 | },
98 | "node_modules/@eslint/eslintrc/node_modules/debug": {
99 | "version": "4.3.4",
100 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
101 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
102 | "dev": true,
103 | "dependencies": {
104 | "ms": "2.1.2"
105 | },
106 | "engines": {
107 | "node": ">=6.0"
108 | },
109 | "peerDependenciesMeta": {
110 | "supports-color": {
111 | "optional": true
112 | }
113 | }
114 | },
115 | "node_modules/@eslint/eslintrc/node_modules/ms": {
116 | "version": "2.1.2",
117 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
118 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
119 | "dev": true
120 | },
121 | "node_modules/@eslint/js": {
122 | "version": "8.56.0",
123 | "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz",
124 | "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==",
125 | "dev": true,
126 | "engines": {
127 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
128 | }
129 | },
130 | "node_modules/@hapi/hoek": {
131 | "version": "9.3.0",
132 | "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
133 | "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ=="
134 | },
135 | "node_modules/@hapi/topo": {
136 | "version": "5.1.0",
137 | "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz",
138 | "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==",
139 | "dependencies": {
140 | "@hapi/hoek": "^9.0.0"
141 | }
142 | },
143 | "node_modules/@humanwhocodes/config-array": {
144 | "version": "0.11.14",
145 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
146 | "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
147 | "dev": true,
148 | "dependencies": {
149 | "@humanwhocodes/object-schema": "^2.0.2",
150 | "debug": "^4.3.1",
151 | "minimatch": "^3.0.5"
152 | },
153 | "engines": {
154 | "node": ">=10.10.0"
155 | }
156 | },
157 | "node_modules/@humanwhocodes/config-array/node_modules/debug": {
158 | "version": "4.3.4",
159 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
160 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
161 | "dev": true,
162 | "dependencies": {
163 | "ms": "2.1.2"
164 | },
165 | "engines": {
166 | "node": ">=6.0"
167 | },
168 | "peerDependenciesMeta": {
169 | "supports-color": {
170 | "optional": true
171 | }
172 | }
173 | },
174 | "node_modules/@humanwhocodes/config-array/node_modules/ms": {
175 | "version": "2.1.2",
176 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
177 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
178 | "dev": true
179 | },
180 | "node_modules/@humanwhocodes/module-importer": {
181 | "version": "1.0.1",
182 | "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
183 | "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
184 | "dev": true,
185 | "engines": {
186 | "node": ">=12.22"
187 | },
188 | "funding": {
189 | "type": "github",
190 | "url": "https://github.com/sponsors/nzakas"
191 | }
192 | },
193 | "node_modules/@humanwhocodes/object-schema": {
194 | "version": "2.0.3",
195 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
196 | "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
197 | "dev": true
198 | },
199 | "node_modules/@jsdoc/salty": {
200 | "version": "0.2.5",
201 | "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.5.tgz",
202 | "integrity": "sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==",
203 | "dev": true,
204 | "dependencies": {
205 | "lodash": "^4.17.21"
206 | },
207 | "engines": {
208 | "node": ">=v12.0.0"
209 | }
210 | },
211 | "node_modules/@mongodb-js/saslprep": {
212 | "version": "1.1.5",
213 | "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.5.tgz",
214 | "integrity": "sha512-XLNOMH66KhJzUJNwT/qlMnS4WsNDWD5ASdyaSH3EtK+F4r/CFGa3jT4GNi4mfOitGvWXtdLgQJkQjxSVrio+jA==",
215 | "dependencies": {
216 | "sparse-bitfield": "^3.0.3"
217 | }
218 | },
219 | "node_modules/@nodelib/fs.scandir": {
220 | "version": "2.1.5",
221 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
222 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
223 | "dev": true,
224 | "dependencies": {
225 | "@nodelib/fs.stat": "2.0.5",
226 | "run-parallel": "^1.1.9"
227 | },
228 | "engines": {
229 | "node": ">= 8"
230 | }
231 | },
232 | "node_modules/@nodelib/fs.stat": {
233 | "version": "2.0.5",
234 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
235 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
236 | "dev": true,
237 | "engines": {
238 | "node": ">= 8"
239 | }
240 | },
241 | "node_modules/@nodelib/fs.walk": {
242 | "version": "1.2.8",
243 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
244 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
245 | "dev": true,
246 | "dependencies": {
247 | "@nodelib/fs.scandir": "2.1.5",
248 | "fastq": "^1.6.0"
249 | },
250 | "engines": {
251 | "node": ">= 8"
252 | }
253 | },
254 | "node_modules/@sideway/address": {
255 | "version": "4.1.4",
256 | "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
257 | "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==",
258 | "dependencies": {
259 | "@hapi/hoek": "^9.0.0"
260 | }
261 | },
262 | "node_modules/@sideway/formula": {
263 | "version": "3.0.1",
264 | "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz",
265 | "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg=="
266 | },
267 | "node_modules/@sideway/pinpoint": {
268 | "version": "2.0.0",
269 | "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
270 | "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ=="
271 | },
272 | "node_modules/@types/linkify-it": {
273 | "version": "3.0.3",
274 | "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.3.tgz",
275 | "integrity": "sha512-pTjcqY9E4nOI55Wgpz7eiI8+LzdYnw3qxXCfHyBDdPbYvbyLgWLJGh8EdPvqawwMK1Uo1794AUkkR38Fr0g+2g==",
276 | "dev": true
277 | },
278 | "node_modules/@types/markdown-it": {
279 | "version": "12.2.3",
280 | "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz",
281 | "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
282 | "dev": true,
283 | "dependencies": {
284 | "@types/linkify-it": "*",
285 | "@types/mdurl": "*"
286 | }
287 | },
288 | "node_modules/@types/mdurl": {
289 | "version": "1.0.2",
290 | "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz",
291 | "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==",
292 | "dev": true
293 | },
294 | "node_modules/@types/webidl-conversions": {
295 | "version": "7.0.3",
296 | "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
297 | "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA=="
298 | },
299 | "node_modules/@types/whatwg-url": {
300 | "version": "11.0.4",
301 | "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz",
302 | "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==",
303 | "dependencies": {
304 | "@types/webidl-conversions": "*"
305 | }
306 | },
307 | "node_modules/@ungap/structured-clone": {
308 | "version": "1.2.0",
309 | "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
310 | "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
311 | "dev": true
312 | },
313 | "node_modules/abbrev": {
314 | "version": "1.1.1",
315 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
316 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
317 | "dev": true
318 | },
319 | "node_modules/accepts": {
320 | "version": "1.3.8",
321 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
322 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
323 | "dependencies": {
324 | "mime-types": "~2.1.34",
325 | "negotiator": "0.6.3"
326 | },
327 | "engines": {
328 | "node": ">= 0.6"
329 | }
330 | },
331 | "node_modules/acorn": {
332 | "version": "8.11.3",
333 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
334 | "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
335 | "dev": true,
336 | "bin": {
337 | "acorn": "bin/acorn"
338 | },
339 | "engines": {
340 | "node": ">=0.4.0"
341 | }
342 | },
343 | "node_modules/acorn-jsx": {
344 | "version": "5.3.2",
345 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
346 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
347 | "dev": true,
348 | "peerDependencies": {
349 | "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
350 | }
351 | },
352 | "node_modules/ajv": {
353 | "version": "6.12.6",
354 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
355 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
356 | "dev": true,
357 | "dependencies": {
358 | "fast-deep-equal": "^3.1.1",
359 | "fast-json-stable-stringify": "^2.0.0",
360 | "json-schema-traverse": "^0.4.1",
361 | "uri-js": "^4.2.2"
362 | },
363 | "funding": {
364 | "type": "github",
365 | "url": "https://github.com/sponsors/epoberezkin"
366 | }
367 | },
368 | "node_modules/ansi-regex": {
369 | "version": "5.0.1",
370 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
371 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
372 | "dev": true,
373 | "engines": {
374 | "node": ">=8"
375 | }
376 | },
377 | "node_modules/ansi-styles": {
378 | "version": "4.3.0",
379 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
380 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
381 | "dev": true,
382 | "dependencies": {
383 | "color-convert": "^2.0.1"
384 | },
385 | "engines": {
386 | "node": ">=8"
387 | },
388 | "funding": {
389 | "url": "https://github.com/chalk/ansi-styles?sponsor=1"
390 | }
391 | },
392 | "node_modules/anymatch": {
393 | "version": "3.1.3",
394 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
395 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
396 | "dev": true,
397 | "dependencies": {
398 | "normalize-path": "^3.0.0",
399 | "picomatch": "^2.0.4"
400 | },
401 | "engines": {
402 | "node": ">= 8"
403 | }
404 | },
405 | "node_modules/argparse": {
406 | "version": "2.0.1",
407 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
408 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
409 | "dev": true
410 | },
411 | "node_modules/array-flatten": {
412 | "version": "1.1.1",
413 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
414 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
415 | },
416 | "node_modules/balanced-match": {
417 | "version": "1.0.2",
418 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
419 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
420 | "dev": true
421 | },
422 | "node_modules/basic-auth": {
423 | "version": "2.0.1",
424 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
425 | "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
426 | "dependencies": {
427 | "safe-buffer": "5.1.2"
428 | },
429 | "engines": {
430 | "node": ">= 0.8"
431 | }
432 | },
433 | "node_modules/basic-auth/node_modules/safe-buffer": {
434 | "version": "5.1.2",
435 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
436 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
437 | },
438 | "node_modules/bcryptjs": {
439 | "version": "2.4.3",
440 | "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
441 | "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ=="
442 | },
443 | "node_modules/binary-extensions": {
444 | "version": "2.2.0",
445 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
446 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
447 | "dev": true,
448 | "engines": {
449 | "node": ">=8"
450 | }
451 | },
452 | "node_modules/bluebird": {
453 | "version": "3.7.2",
454 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
455 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
456 | "dev": true
457 | },
458 | "node_modules/body-parser": {
459 | "version": "1.20.1",
460 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
461 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
462 | "dependencies": {
463 | "bytes": "3.1.2",
464 | "content-type": "~1.0.4",
465 | "debug": "2.6.9",
466 | "depd": "2.0.0",
467 | "destroy": "1.2.0",
468 | "http-errors": "2.0.0",
469 | "iconv-lite": "0.4.24",
470 | "on-finished": "2.4.1",
471 | "qs": "6.11.0",
472 | "raw-body": "2.5.1",
473 | "type-is": "~1.6.18",
474 | "unpipe": "1.0.0"
475 | },
476 | "engines": {
477 | "node": ">= 0.8",
478 | "npm": "1.2.8000 || >= 1.4.16"
479 | }
480 | },
481 | "node_modules/brace-expansion": {
482 | "version": "1.1.11",
483 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
484 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
485 | "dev": true,
486 | "dependencies": {
487 | "balanced-match": "^1.0.0",
488 | "concat-map": "0.0.1"
489 | }
490 | },
491 | "node_modules/braces": {
492 | "version": "3.0.2",
493 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
494 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
495 | "dev": true,
496 | "dependencies": {
497 | "fill-range": "^7.0.1"
498 | },
499 | "engines": {
500 | "node": ">=8"
501 | }
502 | },
503 | "node_modules/bson": {
504 | "version": "6.6.0",
505 | "resolved": "https://registry.npmjs.org/bson/-/bson-6.6.0.tgz",
506 | "integrity": "sha512-BVINv2SgcMjL4oYbBuCQTpE3/VKOSxrOA8Cj/wQP7izSzlBGVomdm+TcUd0Pzy0ytLSSDweCKQ6X3f5veM5LQA==",
507 | "engines": {
508 | "node": ">=16.20.1"
509 | }
510 | },
511 | "node_modules/buffer-equal-constant-time": {
512 | "version": "1.0.1",
513 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
514 | "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
515 | },
516 | "node_modules/bytes": {
517 | "version": "3.1.2",
518 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
519 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
520 | "engines": {
521 | "node": ">= 0.8"
522 | }
523 | },
524 | "node_modules/call-bind": {
525 | "version": "1.0.2",
526 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
527 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
528 | "dependencies": {
529 | "function-bind": "^1.1.1",
530 | "get-intrinsic": "^1.0.2"
531 | },
532 | "funding": {
533 | "url": "https://github.com/sponsors/ljharb"
534 | }
535 | },
536 | "node_modules/callsites": {
537 | "version": "3.1.0",
538 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
539 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
540 | "dev": true,
541 | "engines": {
542 | "node": ">=6"
543 | }
544 | },
545 | "node_modules/catharsis": {
546 | "version": "0.9.0",
547 | "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz",
548 | "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==",
549 | "dev": true,
550 | "dependencies": {
551 | "lodash": "^4.17.15"
552 | },
553 | "engines": {
554 | "node": ">= 10"
555 | }
556 | },
557 | "node_modules/chalk": {
558 | "version": "4.1.2",
559 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
560 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
561 | "dev": true,
562 | "dependencies": {
563 | "ansi-styles": "^4.1.0",
564 | "supports-color": "^7.1.0"
565 | },
566 | "engines": {
567 | "node": ">=10"
568 | },
569 | "funding": {
570 | "url": "https://github.com/chalk/chalk?sponsor=1"
571 | }
572 | },
573 | "node_modules/chokidar": {
574 | "version": "3.5.3",
575 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
576 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
577 | "dev": true,
578 | "funding": [
579 | {
580 | "type": "individual",
581 | "url": "https://paulmillr.com/funding/"
582 | }
583 | ],
584 | "dependencies": {
585 | "anymatch": "~3.1.2",
586 | "braces": "~3.0.2",
587 | "glob-parent": "~5.1.2",
588 | "is-binary-path": "~2.1.0",
589 | "is-glob": "~4.0.1",
590 | "normalize-path": "~3.0.0",
591 | "readdirp": "~3.6.0"
592 | },
593 | "engines": {
594 | "node": ">= 8.10.0"
595 | },
596 | "optionalDependencies": {
597 | "fsevents": "~2.3.2"
598 | }
599 | },
600 | "node_modules/chokidar/node_modules/glob-parent": {
601 | "version": "5.1.2",
602 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
603 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
604 | "dev": true,
605 | "dependencies": {
606 | "is-glob": "^4.0.1"
607 | },
608 | "engines": {
609 | "node": ">= 6"
610 | }
611 | },
612 | "node_modules/color-convert": {
613 | "version": "2.0.1",
614 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
615 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
616 | "dev": true,
617 | "dependencies": {
618 | "color-name": "~1.1.4"
619 | },
620 | "engines": {
621 | "node": ">=7.0.0"
622 | }
623 | },
624 | "node_modules/color-name": {
625 | "version": "1.1.4",
626 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
627 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
628 | "dev": true
629 | },
630 | "node_modules/concat-map": {
631 | "version": "0.0.1",
632 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
633 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
634 | "dev": true
635 | },
636 | "node_modules/content-disposition": {
637 | "version": "0.5.4",
638 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
639 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
640 | "dependencies": {
641 | "safe-buffer": "5.2.1"
642 | },
643 | "engines": {
644 | "node": ">= 0.6"
645 | }
646 | },
647 | "node_modules/content-type": {
648 | "version": "1.0.5",
649 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
650 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
651 | "engines": {
652 | "node": ">= 0.6"
653 | }
654 | },
655 | "node_modules/cookie": {
656 | "version": "0.4.1",
657 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
658 | "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
659 | "engines": {
660 | "node": ">= 0.6"
661 | }
662 | },
663 | "node_modules/cookie-parser": {
664 | "version": "1.4.6",
665 | "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz",
666 | "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==",
667 | "dependencies": {
668 | "cookie": "0.4.1",
669 | "cookie-signature": "1.0.6"
670 | },
671 | "engines": {
672 | "node": ">= 0.8.0"
673 | }
674 | },
675 | "node_modules/cookie-signature": {
676 | "version": "1.0.6",
677 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
678 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
679 | },
680 | "node_modules/cors": {
681 | "version": "2.8.5",
682 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
683 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
684 | "dependencies": {
685 | "object-assign": "^4",
686 | "vary": "^1"
687 | },
688 | "engines": {
689 | "node": ">= 0.10"
690 | }
691 | },
692 | "node_modules/cross-spawn": {
693 | "version": "7.0.3",
694 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
695 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
696 | "dev": true,
697 | "dependencies": {
698 | "path-key": "^3.1.0",
699 | "shebang-command": "^2.0.0",
700 | "which": "^2.0.1"
701 | },
702 | "engines": {
703 | "node": ">= 8"
704 | }
705 | },
706 | "node_modules/debug": {
707 | "version": "2.6.9",
708 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
709 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
710 | "dependencies": {
711 | "ms": "2.0.0"
712 | }
713 | },
714 | "node_modules/deep-is": {
715 | "version": "0.1.4",
716 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
717 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
718 | "dev": true
719 | },
720 | "node_modules/depd": {
721 | "version": "2.0.0",
722 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
723 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
724 | "engines": {
725 | "node": ">= 0.8"
726 | }
727 | },
728 | "node_modules/destroy": {
729 | "version": "1.2.0",
730 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
731 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
732 | "engines": {
733 | "node": ">= 0.8",
734 | "npm": "1.2.8000 || >= 1.4.16"
735 | }
736 | },
737 | "node_modules/doctrine": {
738 | "version": "3.0.0",
739 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
740 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
741 | "dev": true,
742 | "dependencies": {
743 | "esutils": "^2.0.2"
744 | },
745 | "engines": {
746 | "node": ">=6.0.0"
747 | }
748 | },
749 | "node_modules/dotenv": {
750 | "version": "16.4.4",
751 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.4.tgz",
752 | "integrity": "sha512-XvPXc8XAQThSjAbY6cQ/9PcBXmFoWuw1sQ3b8HqUCR6ziGXjkTi//kB9SWa2UwqlgdAIuRqAa/9hVljzPehbYg==",
753 | "engines": {
754 | "node": ">=12"
755 | },
756 | "funding": {
757 | "url": "https://dotenvx.com"
758 | }
759 | },
760 | "node_modules/ecdsa-sig-formatter": {
761 | "version": "1.0.11",
762 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
763 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
764 | "dependencies": {
765 | "safe-buffer": "^5.0.1"
766 | }
767 | },
768 | "node_modules/ee-first": {
769 | "version": "1.1.1",
770 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
771 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
772 | },
773 | "node_modules/encodeurl": {
774 | "version": "1.0.2",
775 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
776 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
777 | "engines": {
778 | "node": ">= 0.8"
779 | }
780 | },
781 | "node_modules/entities": {
782 | "version": "2.1.0",
783 | "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
784 | "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
785 | "dev": true,
786 | "funding": {
787 | "url": "https://github.com/fb55/entities?sponsor=1"
788 | }
789 | },
790 | "node_modules/escape-html": {
791 | "version": "1.0.3",
792 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
793 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
794 | },
795 | "node_modules/escape-string-regexp": {
796 | "version": "4.0.0",
797 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
798 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
799 | "dev": true,
800 | "engines": {
801 | "node": ">=10"
802 | },
803 | "funding": {
804 | "url": "https://github.com/sponsors/sindresorhus"
805 | }
806 | },
807 | "node_modules/eslint": {
808 | "version": "8.56.0",
809 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
810 | "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
811 | "dev": true,
812 | "dependencies": {
813 | "@eslint-community/eslint-utils": "^4.2.0",
814 | "@eslint-community/regexpp": "^4.6.1",
815 | "@eslint/eslintrc": "^2.1.4",
816 | "@eslint/js": "8.56.0",
817 | "@humanwhocodes/config-array": "^0.11.13",
818 | "@humanwhocodes/module-importer": "^1.0.1",
819 | "@nodelib/fs.walk": "^1.2.8",
820 | "@ungap/structured-clone": "^1.2.0",
821 | "ajv": "^6.12.4",
822 | "chalk": "^4.0.0",
823 | "cross-spawn": "^7.0.2",
824 | "debug": "^4.3.2",
825 | "doctrine": "^3.0.0",
826 | "escape-string-regexp": "^4.0.0",
827 | "eslint-scope": "^7.2.2",
828 | "eslint-visitor-keys": "^3.4.3",
829 | "espree": "^9.6.1",
830 | "esquery": "^1.4.2",
831 | "esutils": "^2.0.2",
832 | "fast-deep-equal": "^3.1.3",
833 | "file-entry-cache": "^6.0.1",
834 | "find-up": "^5.0.0",
835 | "glob-parent": "^6.0.2",
836 | "globals": "^13.19.0",
837 | "graphemer": "^1.4.0",
838 | "ignore": "^5.2.0",
839 | "imurmurhash": "^0.1.4",
840 | "is-glob": "^4.0.0",
841 | "is-path-inside": "^3.0.3",
842 | "js-yaml": "^4.1.0",
843 | "json-stable-stringify-without-jsonify": "^1.0.1",
844 | "levn": "^0.4.1",
845 | "lodash.merge": "^4.6.2",
846 | "minimatch": "^3.1.2",
847 | "natural-compare": "^1.4.0",
848 | "optionator": "^0.9.3",
849 | "strip-ansi": "^6.0.1",
850 | "text-table": "^0.2.0"
851 | },
852 | "bin": {
853 | "eslint": "bin/eslint.js"
854 | },
855 | "engines": {
856 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
857 | },
858 | "funding": {
859 | "url": "https://opencollective.com/eslint"
860 | }
861 | },
862 | "node_modules/eslint-config-google": {
863 | "version": "0.14.0",
864 | "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz",
865 | "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==",
866 | "dev": true,
867 | "engines": {
868 | "node": ">=0.10.0"
869 | },
870 | "peerDependencies": {
871 | "eslint": ">=5.16.0"
872 | }
873 | },
874 | "node_modules/eslint-scope": {
875 | "version": "7.2.2",
876 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
877 | "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
878 | "dev": true,
879 | "dependencies": {
880 | "esrecurse": "^4.3.0",
881 | "estraverse": "^5.2.0"
882 | },
883 | "engines": {
884 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
885 | },
886 | "funding": {
887 | "url": "https://opencollective.com/eslint"
888 | }
889 | },
890 | "node_modules/eslint-visitor-keys": {
891 | "version": "3.4.3",
892 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
893 | "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
894 | "dev": true,
895 | "engines": {
896 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
897 | },
898 | "funding": {
899 | "url": "https://opencollective.com/eslint"
900 | }
901 | },
902 | "node_modules/eslint/node_modules/debug": {
903 | "version": "4.3.4",
904 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
905 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
906 | "dev": true,
907 | "dependencies": {
908 | "ms": "2.1.2"
909 | },
910 | "engines": {
911 | "node": ">=6.0"
912 | },
913 | "peerDependenciesMeta": {
914 | "supports-color": {
915 | "optional": true
916 | }
917 | }
918 | },
919 | "node_modules/eslint/node_modules/ms": {
920 | "version": "2.1.2",
921 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
922 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
923 | "dev": true
924 | },
925 | "node_modules/espree": {
926 | "version": "9.6.1",
927 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
928 | "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
929 | "dev": true,
930 | "dependencies": {
931 | "acorn": "^8.9.0",
932 | "acorn-jsx": "^5.3.2",
933 | "eslint-visitor-keys": "^3.4.1"
934 | },
935 | "engines": {
936 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
937 | },
938 | "funding": {
939 | "url": "https://opencollective.com/eslint"
940 | }
941 | },
942 | "node_modules/esquery": {
943 | "version": "1.5.0",
944 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
945 | "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
946 | "dev": true,
947 | "dependencies": {
948 | "estraverse": "^5.1.0"
949 | },
950 | "engines": {
951 | "node": ">=0.10"
952 | }
953 | },
954 | "node_modules/esrecurse": {
955 | "version": "4.3.0",
956 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
957 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
958 | "dev": true,
959 | "dependencies": {
960 | "estraverse": "^5.2.0"
961 | },
962 | "engines": {
963 | "node": ">=4.0"
964 | }
965 | },
966 | "node_modules/estraverse": {
967 | "version": "5.3.0",
968 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
969 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
970 | "dev": true,
971 | "engines": {
972 | "node": ">=4.0"
973 | }
974 | },
975 | "node_modules/esutils": {
976 | "version": "2.0.3",
977 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
978 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
979 | "dev": true,
980 | "engines": {
981 | "node": ">=0.10.0"
982 | }
983 | },
984 | "node_modules/etag": {
985 | "version": "1.8.1",
986 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
987 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
988 | "engines": {
989 | "node": ">= 0.6"
990 | }
991 | },
992 | "node_modules/express": {
993 | "version": "4.18.2",
994 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
995 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
996 | "dependencies": {
997 | "accepts": "~1.3.8",
998 | "array-flatten": "1.1.1",
999 | "body-parser": "1.20.1",
1000 | "content-disposition": "0.5.4",
1001 | "content-type": "~1.0.4",
1002 | "cookie": "0.5.0",
1003 | "cookie-signature": "1.0.6",
1004 | "debug": "2.6.9",
1005 | "depd": "2.0.0",
1006 | "encodeurl": "~1.0.2",
1007 | "escape-html": "~1.0.3",
1008 | "etag": "~1.8.1",
1009 | "finalhandler": "1.2.0",
1010 | "fresh": "0.5.2",
1011 | "http-errors": "2.0.0",
1012 | "merge-descriptors": "1.0.1",
1013 | "methods": "~1.1.2",
1014 | "on-finished": "2.4.1",
1015 | "parseurl": "~1.3.3",
1016 | "path-to-regexp": "0.1.7",
1017 | "proxy-addr": "~2.0.7",
1018 | "qs": "6.11.0",
1019 | "range-parser": "~1.2.1",
1020 | "safe-buffer": "5.2.1",
1021 | "send": "0.18.0",
1022 | "serve-static": "1.15.0",
1023 | "setprototypeof": "1.2.0",
1024 | "statuses": "2.0.1",
1025 | "type-is": "~1.6.18",
1026 | "utils-merge": "1.0.1",
1027 | "vary": "~1.1.2"
1028 | },
1029 | "engines": {
1030 | "node": ">= 0.10.0"
1031 | }
1032 | },
1033 | "node_modules/express/node_modules/cookie": {
1034 | "version": "0.5.0",
1035 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
1036 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
1037 | "engines": {
1038 | "node": ">= 0.6"
1039 | }
1040 | },
1041 | "node_modules/fast-deep-equal": {
1042 | "version": "3.1.3",
1043 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
1044 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
1045 | "dev": true
1046 | },
1047 | "node_modules/fast-json-stable-stringify": {
1048 | "version": "2.1.0",
1049 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
1050 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
1051 | "dev": true
1052 | },
1053 | "node_modules/fast-levenshtein": {
1054 | "version": "2.0.6",
1055 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
1056 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
1057 | "dev": true
1058 | },
1059 | "node_modules/fastq": {
1060 | "version": "1.15.0",
1061 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
1062 | "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
1063 | "dev": true,
1064 | "dependencies": {
1065 | "reusify": "^1.0.4"
1066 | }
1067 | },
1068 | "node_modules/file-entry-cache": {
1069 | "version": "6.0.1",
1070 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
1071 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
1072 | "dev": true,
1073 | "dependencies": {
1074 | "flat-cache": "^3.0.4"
1075 | },
1076 | "engines": {
1077 | "node": "^10.12.0 || >=12.0.0"
1078 | }
1079 | },
1080 | "node_modules/fill-range": {
1081 | "version": "7.0.1",
1082 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
1083 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
1084 | "dev": true,
1085 | "dependencies": {
1086 | "to-regex-range": "^5.0.1"
1087 | },
1088 | "engines": {
1089 | "node": ">=8"
1090 | }
1091 | },
1092 | "node_modules/finalhandler": {
1093 | "version": "1.2.0",
1094 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
1095 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
1096 | "dependencies": {
1097 | "debug": "2.6.9",
1098 | "encodeurl": "~1.0.2",
1099 | "escape-html": "~1.0.3",
1100 | "on-finished": "2.4.1",
1101 | "parseurl": "~1.3.3",
1102 | "statuses": "2.0.1",
1103 | "unpipe": "~1.0.0"
1104 | },
1105 | "engines": {
1106 | "node": ">= 0.8"
1107 | }
1108 | },
1109 | "node_modules/find-up": {
1110 | "version": "5.0.0",
1111 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
1112 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
1113 | "dev": true,
1114 | "dependencies": {
1115 | "locate-path": "^6.0.0",
1116 | "path-exists": "^4.0.0"
1117 | },
1118 | "engines": {
1119 | "node": ">=10"
1120 | },
1121 | "funding": {
1122 | "url": "https://github.com/sponsors/sindresorhus"
1123 | }
1124 | },
1125 | "node_modules/flat-cache": {
1126 | "version": "3.1.0",
1127 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz",
1128 | "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==",
1129 | "dev": true,
1130 | "dependencies": {
1131 | "flatted": "^3.2.7",
1132 | "keyv": "^4.5.3",
1133 | "rimraf": "^3.0.2"
1134 | },
1135 | "engines": {
1136 | "node": ">=12.0.0"
1137 | }
1138 | },
1139 | "node_modules/flatted": {
1140 | "version": "3.2.9",
1141 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
1142 | "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
1143 | "dev": true
1144 | },
1145 | "node_modules/forwarded": {
1146 | "version": "0.2.0",
1147 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
1148 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
1149 | "engines": {
1150 | "node": ">= 0.6"
1151 | }
1152 | },
1153 | "node_modules/fresh": {
1154 | "version": "0.5.2",
1155 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
1156 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
1157 | "engines": {
1158 | "node": ">= 0.6"
1159 | }
1160 | },
1161 | "node_modules/fs.realpath": {
1162 | "version": "1.0.0",
1163 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
1164 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
1165 | "dev": true
1166 | },
1167 | "node_modules/fsevents": {
1168 | "version": "2.3.3",
1169 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
1170 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
1171 | "dev": true,
1172 | "hasInstallScript": true,
1173 | "optional": true,
1174 | "os": [
1175 | "darwin"
1176 | ],
1177 | "engines": {
1178 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1179 | }
1180 | },
1181 | "node_modules/function-bind": {
1182 | "version": "1.1.1",
1183 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
1184 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
1185 | },
1186 | "node_modules/get-intrinsic": {
1187 | "version": "1.2.1",
1188 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
1189 | "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
1190 | "dependencies": {
1191 | "function-bind": "^1.1.1",
1192 | "has": "^1.0.3",
1193 | "has-proto": "^1.0.1",
1194 | "has-symbols": "^1.0.3"
1195 | },
1196 | "funding": {
1197 | "url": "https://github.com/sponsors/ljharb"
1198 | }
1199 | },
1200 | "node_modules/glob": {
1201 | "version": "7.2.3",
1202 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
1203 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
1204 | "dev": true,
1205 | "dependencies": {
1206 | "fs.realpath": "^1.0.0",
1207 | "inflight": "^1.0.4",
1208 | "inherits": "2",
1209 | "minimatch": "^3.1.1",
1210 | "once": "^1.3.0",
1211 | "path-is-absolute": "^1.0.0"
1212 | },
1213 | "engines": {
1214 | "node": "*"
1215 | },
1216 | "funding": {
1217 | "url": "https://github.com/sponsors/isaacs"
1218 | }
1219 | },
1220 | "node_modules/glob-parent": {
1221 | "version": "6.0.2",
1222 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
1223 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
1224 | "dev": true,
1225 | "dependencies": {
1226 | "is-glob": "^4.0.3"
1227 | },
1228 | "engines": {
1229 | "node": ">=10.13.0"
1230 | }
1231 | },
1232 | "node_modules/globals": {
1233 | "version": "13.24.0",
1234 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
1235 | "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
1236 | "dev": true,
1237 | "dependencies": {
1238 | "type-fest": "^0.20.2"
1239 | },
1240 | "engines": {
1241 | "node": ">=8"
1242 | },
1243 | "funding": {
1244 | "url": "https://github.com/sponsors/sindresorhus"
1245 | }
1246 | },
1247 | "node_modules/graceful-fs": {
1248 | "version": "4.2.11",
1249 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
1250 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
1251 | "dev": true
1252 | },
1253 | "node_modules/graphemer": {
1254 | "version": "1.4.0",
1255 | "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
1256 | "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
1257 | "dev": true
1258 | },
1259 | "node_modules/has": {
1260 | "version": "1.0.3",
1261 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
1262 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
1263 | "dependencies": {
1264 | "function-bind": "^1.1.1"
1265 | },
1266 | "engines": {
1267 | "node": ">= 0.4.0"
1268 | }
1269 | },
1270 | "node_modules/has-flag": {
1271 | "version": "4.0.0",
1272 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1273 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
1274 | "dev": true,
1275 | "engines": {
1276 | "node": ">=8"
1277 | }
1278 | },
1279 | "node_modules/has-proto": {
1280 | "version": "1.0.1",
1281 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
1282 | "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
1283 | "engines": {
1284 | "node": ">= 0.4"
1285 | },
1286 | "funding": {
1287 | "url": "https://github.com/sponsors/ljharb"
1288 | }
1289 | },
1290 | "node_modules/has-symbols": {
1291 | "version": "1.0.3",
1292 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
1293 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
1294 | "engines": {
1295 | "node": ">= 0.4"
1296 | },
1297 | "funding": {
1298 | "url": "https://github.com/sponsors/ljharb"
1299 | }
1300 | },
1301 | "node_modules/http-errors": {
1302 | "version": "2.0.0",
1303 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
1304 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
1305 | "dependencies": {
1306 | "depd": "2.0.0",
1307 | "inherits": "2.0.4",
1308 | "setprototypeof": "1.2.0",
1309 | "statuses": "2.0.1",
1310 | "toidentifier": "1.0.1"
1311 | },
1312 | "engines": {
1313 | "node": ">= 0.8"
1314 | }
1315 | },
1316 | "node_modules/iconv-lite": {
1317 | "version": "0.4.24",
1318 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
1319 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
1320 | "dependencies": {
1321 | "safer-buffer": ">= 2.1.2 < 3"
1322 | },
1323 | "engines": {
1324 | "node": ">=0.10.0"
1325 | }
1326 | },
1327 | "node_modules/ignore": {
1328 | "version": "5.3.1",
1329 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
1330 | "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
1331 | "dev": true,
1332 | "engines": {
1333 | "node": ">= 4"
1334 | }
1335 | },
1336 | "node_modules/ignore-by-default": {
1337 | "version": "1.0.1",
1338 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
1339 | "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
1340 | "dev": true
1341 | },
1342 | "node_modules/import-fresh": {
1343 | "version": "3.3.0",
1344 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
1345 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
1346 | "dev": true,
1347 | "dependencies": {
1348 | "parent-module": "^1.0.0",
1349 | "resolve-from": "^4.0.0"
1350 | },
1351 | "engines": {
1352 | "node": ">=6"
1353 | },
1354 | "funding": {
1355 | "url": "https://github.com/sponsors/sindresorhus"
1356 | }
1357 | },
1358 | "node_modules/imurmurhash": {
1359 | "version": "0.1.4",
1360 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
1361 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
1362 | "dev": true,
1363 | "engines": {
1364 | "node": ">=0.8.19"
1365 | }
1366 | },
1367 | "node_modules/inflight": {
1368 | "version": "1.0.6",
1369 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
1370 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
1371 | "dev": true,
1372 | "dependencies": {
1373 | "once": "^1.3.0",
1374 | "wrappy": "1"
1375 | }
1376 | },
1377 | "node_modules/inherits": {
1378 | "version": "2.0.4",
1379 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1380 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
1381 | },
1382 | "node_modules/ipaddr.js": {
1383 | "version": "1.9.1",
1384 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
1385 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
1386 | "engines": {
1387 | "node": ">= 0.10"
1388 | }
1389 | },
1390 | "node_modules/is-binary-path": {
1391 | "version": "2.1.0",
1392 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
1393 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
1394 | "dev": true,
1395 | "dependencies": {
1396 | "binary-extensions": "^2.0.0"
1397 | },
1398 | "engines": {
1399 | "node": ">=8"
1400 | }
1401 | },
1402 | "node_modules/is-extglob": {
1403 | "version": "2.1.1",
1404 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
1405 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
1406 | "dev": true,
1407 | "engines": {
1408 | "node": ">=0.10.0"
1409 | }
1410 | },
1411 | "node_modules/is-glob": {
1412 | "version": "4.0.3",
1413 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
1414 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
1415 | "dev": true,
1416 | "dependencies": {
1417 | "is-extglob": "^2.1.1"
1418 | },
1419 | "engines": {
1420 | "node": ">=0.10.0"
1421 | }
1422 | },
1423 | "node_modules/is-number": {
1424 | "version": "7.0.0",
1425 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
1426 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
1427 | "dev": true,
1428 | "engines": {
1429 | "node": ">=0.12.0"
1430 | }
1431 | },
1432 | "node_modules/is-path-inside": {
1433 | "version": "3.0.3",
1434 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
1435 | "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
1436 | "dev": true,
1437 | "engines": {
1438 | "node": ">=8"
1439 | }
1440 | },
1441 | "node_modules/isexe": {
1442 | "version": "2.0.0",
1443 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
1444 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
1445 | "dev": true
1446 | },
1447 | "node_modules/joi": {
1448 | "version": "17.10.2",
1449 | "resolved": "https://registry.npmjs.org/joi/-/joi-17.10.2.tgz",
1450 | "integrity": "sha512-hcVhjBxRNW/is3nNLdGLIjkgXetkeGc2wyhydhz8KumG23Aerk4HPjU5zaPAMRqXQFc0xNqXTC7+zQjxr0GlKA==",
1451 | "dependencies": {
1452 | "@hapi/hoek": "^9.0.0",
1453 | "@hapi/topo": "^5.0.0",
1454 | "@sideway/address": "^4.1.3",
1455 | "@sideway/formula": "^3.0.1",
1456 | "@sideway/pinpoint": "^2.0.0"
1457 | }
1458 | },
1459 | "node_modules/js-yaml": {
1460 | "version": "4.1.0",
1461 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
1462 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
1463 | "dev": true,
1464 | "dependencies": {
1465 | "argparse": "^2.0.1"
1466 | },
1467 | "bin": {
1468 | "js-yaml": "bin/js-yaml.js"
1469 | }
1470 | },
1471 | "node_modules/js2xmlparser": {
1472 | "version": "4.0.2",
1473 | "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz",
1474 | "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==",
1475 | "dev": true,
1476 | "dependencies": {
1477 | "xmlcreate": "^2.0.4"
1478 | }
1479 | },
1480 | "node_modules/jsdoc": {
1481 | "version": "4.0.2",
1482 | "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz",
1483 | "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==",
1484 | "dev": true,
1485 | "dependencies": {
1486 | "@babel/parser": "^7.20.15",
1487 | "@jsdoc/salty": "^0.2.1",
1488 | "@types/markdown-it": "^12.2.3",
1489 | "bluebird": "^3.7.2",
1490 | "catharsis": "^0.9.0",
1491 | "escape-string-regexp": "^2.0.0",
1492 | "js2xmlparser": "^4.0.2",
1493 | "klaw": "^3.0.0",
1494 | "markdown-it": "^12.3.2",
1495 | "markdown-it-anchor": "^8.4.1",
1496 | "marked": "^4.0.10",
1497 | "mkdirp": "^1.0.4",
1498 | "requizzle": "^0.2.3",
1499 | "strip-json-comments": "^3.1.0",
1500 | "underscore": "~1.13.2"
1501 | },
1502 | "bin": {
1503 | "jsdoc": "jsdoc.js"
1504 | },
1505 | "engines": {
1506 | "node": ">=12.0.0"
1507 | }
1508 | },
1509 | "node_modules/jsdoc/node_modules/escape-string-regexp": {
1510 | "version": "2.0.0",
1511 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
1512 | "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
1513 | "dev": true,
1514 | "engines": {
1515 | "node": ">=8"
1516 | }
1517 | },
1518 | "node_modules/json-buffer": {
1519 | "version": "3.0.1",
1520 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
1521 | "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
1522 | "dev": true
1523 | },
1524 | "node_modules/json-schema-traverse": {
1525 | "version": "0.4.1",
1526 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
1527 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
1528 | "dev": true
1529 | },
1530 | "node_modules/json-stable-stringify-without-jsonify": {
1531 | "version": "1.0.1",
1532 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
1533 | "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
1534 | "dev": true
1535 | },
1536 | "node_modules/jsonwebtoken": {
1537 | "version": "9.0.2",
1538 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
1539 | "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
1540 | "dependencies": {
1541 | "jws": "^3.2.2",
1542 | "lodash.includes": "^4.3.0",
1543 | "lodash.isboolean": "^3.0.3",
1544 | "lodash.isinteger": "^4.0.4",
1545 | "lodash.isnumber": "^3.0.3",
1546 | "lodash.isplainobject": "^4.0.6",
1547 | "lodash.isstring": "^4.0.1",
1548 | "lodash.once": "^4.0.0",
1549 | "ms": "^2.1.1",
1550 | "semver": "^7.5.4"
1551 | },
1552 | "engines": {
1553 | "node": ">=12",
1554 | "npm": ">=6"
1555 | }
1556 | },
1557 | "node_modules/jsonwebtoken/node_modules/ms": {
1558 | "version": "2.1.3",
1559 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1560 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
1561 | },
1562 | "node_modules/jwa": {
1563 | "version": "1.4.1",
1564 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
1565 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
1566 | "dependencies": {
1567 | "buffer-equal-constant-time": "1.0.1",
1568 | "ecdsa-sig-formatter": "1.0.11",
1569 | "safe-buffer": "^5.0.1"
1570 | }
1571 | },
1572 | "node_modules/jws": {
1573 | "version": "3.2.2",
1574 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
1575 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
1576 | "dependencies": {
1577 | "jwa": "^1.4.1",
1578 | "safe-buffer": "^5.0.1"
1579 | }
1580 | },
1581 | "node_modules/kareem": {
1582 | "version": "2.5.1",
1583 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz",
1584 | "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==",
1585 | "engines": {
1586 | "node": ">=12.0.0"
1587 | }
1588 | },
1589 | "node_modules/keyv": {
1590 | "version": "4.5.3",
1591 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz",
1592 | "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==",
1593 | "dev": true,
1594 | "dependencies": {
1595 | "json-buffer": "3.0.1"
1596 | }
1597 | },
1598 | "node_modules/klaw": {
1599 | "version": "3.0.0",
1600 | "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz",
1601 | "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==",
1602 | "dev": true,
1603 | "dependencies": {
1604 | "graceful-fs": "^4.1.9"
1605 | }
1606 | },
1607 | "node_modules/levn": {
1608 | "version": "0.4.1",
1609 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
1610 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
1611 | "dev": true,
1612 | "dependencies": {
1613 | "prelude-ls": "^1.2.1",
1614 | "type-check": "~0.4.0"
1615 | },
1616 | "engines": {
1617 | "node": ">= 0.8.0"
1618 | }
1619 | },
1620 | "node_modules/linkify-it": {
1621 | "version": "3.0.3",
1622 | "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
1623 | "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
1624 | "dev": true,
1625 | "dependencies": {
1626 | "uc.micro": "^1.0.1"
1627 | }
1628 | },
1629 | "node_modules/locate-path": {
1630 | "version": "6.0.0",
1631 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
1632 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
1633 | "dev": true,
1634 | "dependencies": {
1635 | "p-locate": "^5.0.0"
1636 | },
1637 | "engines": {
1638 | "node": ">=10"
1639 | },
1640 | "funding": {
1641 | "url": "https://github.com/sponsors/sindresorhus"
1642 | }
1643 | },
1644 | "node_modules/lodash": {
1645 | "version": "4.17.21",
1646 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
1647 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
1648 | "dev": true
1649 | },
1650 | "node_modules/lodash.includes": {
1651 | "version": "4.3.0",
1652 | "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
1653 | "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
1654 | },
1655 | "node_modules/lodash.isboolean": {
1656 | "version": "3.0.3",
1657 | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
1658 | "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
1659 | },
1660 | "node_modules/lodash.isinteger": {
1661 | "version": "4.0.4",
1662 | "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
1663 | "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
1664 | },
1665 | "node_modules/lodash.isnumber": {
1666 | "version": "3.0.3",
1667 | "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
1668 | "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
1669 | },
1670 | "node_modules/lodash.isplainobject": {
1671 | "version": "4.0.6",
1672 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
1673 | "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
1674 | },
1675 | "node_modules/lodash.isstring": {
1676 | "version": "4.0.1",
1677 | "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
1678 | "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
1679 | },
1680 | "node_modules/lodash.merge": {
1681 | "version": "4.6.2",
1682 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
1683 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
1684 | "dev": true
1685 | },
1686 | "node_modules/lodash.once": {
1687 | "version": "4.1.1",
1688 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
1689 | "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
1690 | },
1691 | "node_modules/lru-cache": {
1692 | "version": "6.0.0",
1693 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
1694 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
1695 | "dependencies": {
1696 | "yallist": "^4.0.0"
1697 | },
1698 | "engines": {
1699 | "node": ">=10"
1700 | }
1701 | },
1702 | "node_modules/markdown-it": {
1703 | "version": "12.3.2",
1704 | "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
1705 | "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
1706 | "dev": true,
1707 | "dependencies": {
1708 | "argparse": "^2.0.1",
1709 | "entities": "~2.1.0",
1710 | "linkify-it": "^3.0.1",
1711 | "mdurl": "^1.0.1",
1712 | "uc.micro": "^1.0.5"
1713 | },
1714 | "bin": {
1715 | "markdown-it": "bin/markdown-it.js"
1716 | }
1717 | },
1718 | "node_modules/markdown-it-anchor": {
1719 | "version": "8.6.7",
1720 | "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz",
1721 | "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==",
1722 | "dev": true,
1723 | "peerDependencies": {
1724 | "@types/markdown-it": "*",
1725 | "markdown-it": "*"
1726 | }
1727 | },
1728 | "node_modules/marked": {
1729 | "version": "4.3.0",
1730 | "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz",
1731 | "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==",
1732 | "dev": true,
1733 | "bin": {
1734 | "marked": "bin/marked.js"
1735 | },
1736 | "engines": {
1737 | "node": ">= 12"
1738 | }
1739 | },
1740 | "node_modules/mdurl": {
1741 | "version": "1.0.1",
1742 | "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
1743 | "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==",
1744 | "dev": true
1745 | },
1746 | "node_modules/media-typer": {
1747 | "version": "0.3.0",
1748 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
1749 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
1750 | "engines": {
1751 | "node": ">= 0.6"
1752 | }
1753 | },
1754 | "node_modules/memory-pager": {
1755 | "version": "1.5.0",
1756 | "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
1757 | "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg=="
1758 | },
1759 | "node_modules/merge-descriptors": {
1760 | "version": "1.0.1",
1761 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
1762 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
1763 | },
1764 | "node_modules/methods": {
1765 | "version": "1.1.2",
1766 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
1767 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
1768 | "engines": {
1769 | "node": ">= 0.6"
1770 | }
1771 | },
1772 | "node_modules/mime": {
1773 | "version": "1.6.0",
1774 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
1775 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
1776 | "bin": {
1777 | "mime": "cli.js"
1778 | },
1779 | "engines": {
1780 | "node": ">=4"
1781 | }
1782 | },
1783 | "node_modules/mime-db": {
1784 | "version": "1.52.0",
1785 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
1786 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
1787 | "engines": {
1788 | "node": ">= 0.6"
1789 | }
1790 | },
1791 | "node_modules/mime-types": {
1792 | "version": "2.1.35",
1793 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
1794 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
1795 | "dependencies": {
1796 | "mime-db": "1.52.0"
1797 | },
1798 | "engines": {
1799 | "node": ">= 0.6"
1800 | }
1801 | },
1802 | "node_modules/minimatch": {
1803 | "version": "3.1.2",
1804 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1805 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1806 | "dev": true,
1807 | "dependencies": {
1808 | "brace-expansion": "^1.1.7"
1809 | },
1810 | "engines": {
1811 | "node": "*"
1812 | }
1813 | },
1814 | "node_modules/mkdirp": {
1815 | "version": "1.0.4",
1816 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
1817 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
1818 | "dev": true,
1819 | "bin": {
1820 | "mkdirp": "bin/cmd.js"
1821 | },
1822 | "engines": {
1823 | "node": ">=10"
1824 | }
1825 | },
1826 | "node_modules/mongodb": {
1827 | "version": "6.3.0",
1828 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.3.0.tgz",
1829 | "integrity": "sha512-tt0KuGjGtLUhLoU263+xvQmPHEGTw5LbcNC73EoFRYgSHwZt5tsoJC110hDyO1kjQzpgNrpdcSza9PknWN4LrA==",
1830 | "dependencies": {
1831 | "@mongodb-js/saslprep": "^1.1.0",
1832 | "bson": "^6.2.0",
1833 | "mongodb-connection-string-url": "^3.0.0"
1834 | },
1835 | "engines": {
1836 | "node": ">=16.20.1"
1837 | },
1838 | "peerDependencies": {
1839 | "@aws-sdk/credential-providers": "^3.188.0",
1840 | "@mongodb-js/zstd": "^1.1.0",
1841 | "gcp-metadata": "^5.2.0",
1842 | "kerberos": "^2.0.1",
1843 | "mongodb-client-encryption": ">=6.0.0 <7",
1844 | "snappy": "^7.2.2",
1845 | "socks": "^2.7.1"
1846 | },
1847 | "peerDependenciesMeta": {
1848 | "@aws-sdk/credential-providers": {
1849 | "optional": true
1850 | },
1851 | "@mongodb-js/zstd": {
1852 | "optional": true
1853 | },
1854 | "gcp-metadata": {
1855 | "optional": true
1856 | },
1857 | "kerberos": {
1858 | "optional": true
1859 | },
1860 | "mongodb-client-encryption": {
1861 | "optional": true
1862 | },
1863 | "snappy": {
1864 | "optional": true
1865 | },
1866 | "socks": {
1867 | "optional": true
1868 | }
1869 | }
1870 | },
1871 | "node_modules/mongodb-connection-string-url": {
1872 | "version": "3.0.0",
1873 | "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz",
1874 | "integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==",
1875 | "dependencies": {
1876 | "@types/whatwg-url": "^11.0.2",
1877 | "whatwg-url": "^13.0.0"
1878 | }
1879 | },
1880 | "node_modules/mongoose": {
1881 | "version": "8.1.0",
1882 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.1.0.tgz",
1883 | "integrity": "sha512-kOA4Xnq2goqNpN9EmYElGNWfxA9H80fxcr7UdJKWi3UMflza0R7wpTihCpM67dE/0MNFljoa0sjQtlXVkkySAQ==",
1884 | "dependencies": {
1885 | "bson": "^6.2.0",
1886 | "kareem": "2.5.1",
1887 | "mongodb": "6.3.0",
1888 | "mpath": "0.9.0",
1889 | "mquery": "5.0.0",
1890 | "ms": "2.1.3",
1891 | "sift": "16.0.1"
1892 | },
1893 | "engines": {
1894 | "node": ">=16.20.1"
1895 | },
1896 | "funding": {
1897 | "type": "opencollective",
1898 | "url": "https://opencollective.com/mongoose"
1899 | }
1900 | },
1901 | "node_modules/mongoose/node_modules/ms": {
1902 | "version": "2.1.3",
1903 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1904 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
1905 | },
1906 | "node_modules/morgan": {
1907 | "version": "1.10.0",
1908 | "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz",
1909 | "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==",
1910 | "dependencies": {
1911 | "basic-auth": "~2.0.1",
1912 | "debug": "2.6.9",
1913 | "depd": "~2.0.0",
1914 | "on-finished": "~2.3.0",
1915 | "on-headers": "~1.0.2"
1916 | },
1917 | "engines": {
1918 | "node": ">= 0.8.0"
1919 | }
1920 | },
1921 | "node_modules/morgan/node_modules/on-finished": {
1922 | "version": "2.3.0",
1923 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
1924 | "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
1925 | "dependencies": {
1926 | "ee-first": "1.1.1"
1927 | },
1928 | "engines": {
1929 | "node": ">= 0.8"
1930 | }
1931 | },
1932 | "node_modules/mpath": {
1933 | "version": "0.9.0",
1934 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz",
1935 | "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==",
1936 | "engines": {
1937 | "node": ">=4.0.0"
1938 | }
1939 | },
1940 | "node_modules/mquery": {
1941 | "version": "5.0.0",
1942 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz",
1943 | "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==",
1944 | "dependencies": {
1945 | "debug": "4.x"
1946 | },
1947 | "engines": {
1948 | "node": ">=14.0.0"
1949 | }
1950 | },
1951 | "node_modules/mquery/node_modules/debug": {
1952 | "version": "4.3.4",
1953 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
1954 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
1955 | "dependencies": {
1956 | "ms": "2.1.2"
1957 | },
1958 | "engines": {
1959 | "node": ">=6.0"
1960 | },
1961 | "peerDependenciesMeta": {
1962 | "supports-color": {
1963 | "optional": true
1964 | }
1965 | }
1966 | },
1967 | "node_modules/mquery/node_modules/ms": {
1968 | "version": "2.1.2",
1969 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
1970 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
1971 | },
1972 | "node_modules/ms": {
1973 | "version": "2.0.0",
1974 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1975 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
1976 | },
1977 | "node_modules/natural-compare": {
1978 | "version": "1.4.0",
1979 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
1980 | "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
1981 | "dev": true
1982 | },
1983 | "node_modules/negotiator": {
1984 | "version": "0.6.3",
1985 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
1986 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
1987 | "engines": {
1988 | "node": ">= 0.6"
1989 | }
1990 | },
1991 | "node_modules/nodemon": {
1992 | "version": "3.0.3",
1993 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.3.tgz",
1994 | "integrity": "sha512-7jH/NXbFPxVaMwmBCC2B9F/V6X1VkEdNgx3iu9jji8WxWcvhMWkmhNWhI5077zknOnZnBzba9hZP6bCPJLSReQ==",
1995 | "dev": true,
1996 | "dependencies": {
1997 | "chokidar": "^3.5.2",
1998 | "debug": "^4",
1999 | "ignore-by-default": "^1.0.1",
2000 | "minimatch": "^3.1.2",
2001 | "pstree.remy": "^1.1.8",
2002 | "semver": "^7.5.3",
2003 | "simple-update-notifier": "^2.0.0",
2004 | "supports-color": "^5.5.0",
2005 | "touch": "^3.1.0",
2006 | "undefsafe": "^2.0.5"
2007 | },
2008 | "bin": {
2009 | "nodemon": "bin/nodemon.js"
2010 | },
2011 | "engines": {
2012 | "node": ">=10"
2013 | },
2014 | "funding": {
2015 | "type": "opencollective",
2016 | "url": "https://opencollective.com/nodemon"
2017 | }
2018 | },
2019 | "node_modules/nodemon/node_modules/debug": {
2020 | "version": "4.3.4",
2021 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
2022 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
2023 | "dev": true,
2024 | "dependencies": {
2025 | "ms": "2.1.2"
2026 | },
2027 | "engines": {
2028 | "node": ">=6.0"
2029 | },
2030 | "peerDependenciesMeta": {
2031 | "supports-color": {
2032 | "optional": true
2033 | }
2034 | }
2035 | },
2036 | "node_modules/nodemon/node_modules/has-flag": {
2037 | "version": "3.0.0",
2038 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
2039 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
2040 | "dev": true,
2041 | "engines": {
2042 | "node": ">=4"
2043 | }
2044 | },
2045 | "node_modules/nodemon/node_modules/ms": {
2046 | "version": "2.1.2",
2047 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
2048 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
2049 | "dev": true
2050 | },
2051 | "node_modules/nodemon/node_modules/supports-color": {
2052 | "version": "5.5.0",
2053 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
2054 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
2055 | "dev": true,
2056 | "dependencies": {
2057 | "has-flag": "^3.0.0"
2058 | },
2059 | "engines": {
2060 | "node": ">=4"
2061 | }
2062 | },
2063 | "node_modules/nopt": {
2064 | "version": "1.0.10",
2065 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
2066 | "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
2067 | "dev": true,
2068 | "dependencies": {
2069 | "abbrev": "1"
2070 | },
2071 | "bin": {
2072 | "nopt": "bin/nopt.js"
2073 | },
2074 | "engines": {
2075 | "node": "*"
2076 | }
2077 | },
2078 | "node_modules/normalize-path": {
2079 | "version": "3.0.0",
2080 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
2081 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
2082 | "dev": true,
2083 | "engines": {
2084 | "node": ">=0.10.0"
2085 | }
2086 | },
2087 | "node_modules/object-assign": {
2088 | "version": "4.1.1",
2089 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
2090 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
2091 | "engines": {
2092 | "node": ">=0.10.0"
2093 | }
2094 | },
2095 | "node_modules/object-inspect": {
2096 | "version": "1.12.3",
2097 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
2098 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
2099 | "funding": {
2100 | "url": "https://github.com/sponsors/ljharb"
2101 | }
2102 | },
2103 | "node_modules/on-finished": {
2104 | "version": "2.4.1",
2105 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
2106 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
2107 | "dependencies": {
2108 | "ee-first": "1.1.1"
2109 | },
2110 | "engines": {
2111 | "node": ">= 0.8"
2112 | }
2113 | },
2114 | "node_modules/on-headers": {
2115 | "version": "1.0.2",
2116 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
2117 | "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
2118 | "engines": {
2119 | "node": ">= 0.8"
2120 | }
2121 | },
2122 | "node_modules/once": {
2123 | "version": "1.4.0",
2124 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
2125 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
2126 | "dev": true,
2127 | "dependencies": {
2128 | "wrappy": "1"
2129 | }
2130 | },
2131 | "node_modules/optionator": {
2132 | "version": "0.9.3",
2133 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
2134 | "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
2135 | "dev": true,
2136 | "dependencies": {
2137 | "@aashutoshrathi/word-wrap": "^1.2.3",
2138 | "deep-is": "^0.1.3",
2139 | "fast-levenshtein": "^2.0.6",
2140 | "levn": "^0.4.1",
2141 | "prelude-ls": "^1.2.1",
2142 | "type-check": "^0.4.0"
2143 | },
2144 | "engines": {
2145 | "node": ">= 0.8.0"
2146 | }
2147 | },
2148 | "node_modules/p-limit": {
2149 | "version": "3.1.0",
2150 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
2151 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
2152 | "dev": true,
2153 | "dependencies": {
2154 | "yocto-queue": "^0.1.0"
2155 | },
2156 | "engines": {
2157 | "node": ">=10"
2158 | },
2159 | "funding": {
2160 | "url": "https://github.com/sponsors/sindresorhus"
2161 | }
2162 | },
2163 | "node_modules/p-locate": {
2164 | "version": "5.0.0",
2165 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
2166 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
2167 | "dev": true,
2168 | "dependencies": {
2169 | "p-limit": "^3.0.2"
2170 | },
2171 | "engines": {
2172 | "node": ">=10"
2173 | },
2174 | "funding": {
2175 | "url": "https://github.com/sponsors/sindresorhus"
2176 | }
2177 | },
2178 | "node_modules/parent-module": {
2179 | "version": "1.0.1",
2180 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
2181 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
2182 | "dev": true,
2183 | "dependencies": {
2184 | "callsites": "^3.0.0"
2185 | },
2186 | "engines": {
2187 | "node": ">=6"
2188 | }
2189 | },
2190 | "node_modules/parseurl": {
2191 | "version": "1.3.3",
2192 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
2193 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
2194 | "engines": {
2195 | "node": ">= 0.8"
2196 | }
2197 | },
2198 | "node_modules/path-exists": {
2199 | "version": "4.0.0",
2200 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
2201 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
2202 | "dev": true,
2203 | "engines": {
2204 | "node": ">=8"
2205 | }
2206 | },
2207 | "node_modules/path-is-absolute": {
2208 | "version": "1.0.1",
2209 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
2210 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
2211 | "dev": true,
2212 | "engines": {
2213 | "node": ">=0.10.0"
2214 | }
2215 | },
2216 | "node_modules/path-key": {
2217 | "version": "3.1.1",
2218 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
2219 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
2220 | "dev": true,
2221 | "engines": {
2222 | "node": ">=8"
2223 | }
2224 | },
2225 | "node_modules/path-to-regexp": {
2226 | "version": "0.1.7",
2227 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
2228 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
2229 | },
2230 | "node_modules/picomatch": {
2231 | "version": "2.3.1",
2232 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
2233 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
2234 | "dev": true,
2235 | "engines": {
2236 | "node": ">=8.6"
2237 | },
2238 | "funding": {
2239 | "url": "https://github.com/sponsors/jonschlinkert"
2240 | }
2241 | },
2242 | "node_modules/prelude-ls": {
2243 | "version": "1.2.1",
2244 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
2245 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
2246 | "dev": true,
2247 | "engines": {
2248 | "node": ">= 0.8.0"
2249 | }
2250 | },
2251 | "node_modules/prettier": {
2252 | "version": "3.2.5",
2253 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
2254 | "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
2255 | "dev": true,
2256 | "bin": {
2257 | "prettier": "bin/prettier.cjs"
2258 | },
2259 | "engines": {
2260 | "node": ">=14"
2261 | },
2262 | "funding": {
2263 | "url": "https://github.com/prettier/prettier?sponsor=1"
2264 | }
2265 | },
2266 | "node_modules/proxy-addr": {
2267 | "version": "2.0.7",
2268 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
2269 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
2270 | "dependencies": {
2271 | "forwarded": "0.2.0",
2272 | "ipaddr.js": "1.9.1"
2273 | },
2274 | "engines": {
2275 | "node": ">= 0.10"
2276 | }
2277 | },
2278 | "node_modules/pstree.remy": {
2279 | "version": "1.1.8",
2280 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
2281 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
2282 | "dev": true
2283 | },
2284 | "node_modules/punycode": {
2285 | "version": "2.3.0",
2286 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
2287 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
2288 | "engines": {
2289 | "node": ">=6"
2290 | }
2291 | },
2292 | "node_modules/qs": {
2293 | "version": "6.11.0",
2294 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
2295 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
2296 | "dependencies": {
2297 | "side-channel": "^1.0.4"
2298 | },
2299 | "engines": {
2300 | "node": ">=0.6"
2301 | },
2302 | "funding": {
2303 | "url": "https://github.com/sponsors/ljharb"
2304 | }
2305 | },
2306 | "node_modules/queue-microtask": {
2307 | "version": "1.2.3",
2308 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
2309 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
2310 | "dev": true,
2311 | "funding": [
2312 | {
2313 | "type": "github",
2314 | "url": "https://github.com/sponsors/feross"
2315 | },
2316 | {
2317 | "type": "patreon",
2318 | "url": "https://www.patreon.com/feross"
2319 | },
2320 | {
2321 | "type": "consulting",
2322 | "url": "https://feross.org/support"
2323 | }
2324 | ]
2325 | },
2326 | "node_modules/range-parser": {
2327 | "version": "1.2.1",
2328 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
2329 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
2330 | "engines": {
2331 | "node": ">= 0.6"
2332 | }
2333 | },
2334 | "node_modules/raw-body": {
2335 | "version": "2.5.1",
2336 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
2337 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
2338 | "dependencies": {
2339 | "bytes": "3.1.2",
2340 | "http-errors": "2.0.0",
2341 | "iconv-lite": "0.4.24",
2342 | "unpipe": "1.0.0"
2343 | },
2344 | "engines": {
2345 | "node": ">= 0.8"
2346 | }
2347 | },
2348 | "node_modules/readdirp": {
2349 | "version": "3.6.0",
2350 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
2351 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
2352 | "dev": true,
2353 | "dependencies": {
2354 | "picomatch": "^2.2.1"
2355 | },
2356 | "engines": {
2357 | "node": ">=8.10.0"
2358 | }
2359 | },
2360 | "node_modules/requizzle": {
2361 | "version": "0.2.4",
2362 | "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz",
2363 | "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==",
2364 | "dev": true,
2365 | "dependencies": {
2366 | "lodash": "^4.17.21"
2367 | }
2368 | },
2369 | "node_modules/resolve-from": {
2370 | "version": "4.0.0",
2371 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
2372 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
2373 | "dev": true,
2374 | "engines": {
2375 | "node": ">=4"
2376 | }
2377 | },
2378 | "node_modules/reusify": {
2379 | "version": "1.0.4",
2380 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
2381 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
2382 | "dev": true,
2383 | "engines": {
2384 | "iojs": ">=1.0.0",
2385 | "node": ">=0.10.0"
2386 | }
2387 | },
2388 | "node_modules/rimraf": {
2389 | "version": "3.0.2",
2390 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
2391 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
2392 | "dev": true,
2393 | "dependencies": {
2394 | "glob": "^7.1.3"
2395 | },
2396 | "bin": {
2397 | "rimraf": "bin.js"
2398 | },
2399 | "funding": {
2400 | "url": "https://github.com/sponsors/isaacs"
2401 | }
2402 | },
2403 | "node_modules/run-parallel": {
2404 | "version": "1.2.0",
2405 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
2406 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
2407 | "dev": true,
2408 | "funding": [
2409 | {
2410 | "type": "github",
2411 | "url": "https://github.com/sponsors/feross"
2412 | },
2413 | {
2414 | "type": "patreon",
2415 | "url": "https://www.patreon.com/feross"
2416 | },
2417 | {
2418 | "type": "consulting",
2419 | "url": "https://feross.org/support"
2420 | }
2421 | ],
2422 | "dependencies": {
2423 | "queue-microtask": "^1.2.2"
2424 | }
2425 | },
2426 | "node_modules/safe-buffer": {
2427 | "version": "5.2.1",
2428 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
2429 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
2430 | "funding": [
2431 | {
2432 | "type": "github",
2433 | "url": "https://github.com/sponsors/feross"
2434 | },
2435 | {
2436 | "type": "patreon",
2437 | "url": "https://www.patreon.com/feross"
2438 | },
2439 | {
2440 | "type": "consulting",
2441 | "url": "https://feross.org/support"
2442 | }
2443 | ]
2444 | },
2445 | "node_modules/safer-buffer": {
2446 | "version": "2.1.2",
2447 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
2448 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
2449 | },
2450 | "node_modules/semver": {
2451 | "version": "7.5.4",
2452 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
2453 | "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
2454 | "dependencies": {
2455 | "lru-cache": "^6.0.0"
2456 | },
2457 | "bin": {
2458 | "semver": "bin/semver.js"
2459 | },
2460 | "engines": {
2461 | "node": ">=10"
2462 | }
2463 | },
2464 | "node_modules/send": {
2465 | "version": "0.18.0",
2466 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
2467 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
2468 | "dependencies": {
2469 | "debug": "2.6.9",
2470 | "depd": "2.0.0",
2471 | "destroy": "1.2.0",
2472 | "encodeurl": "~1.0.2",
2473 | "escape-html": "~1.0.3",
2474 | "etag": "~1.8.1",
2475 | "fresh": "0.5.2",
2476 | "http-errors": "2.0.0",
2477 | "mime": "1.6.0",
2478 | "ms": "2.1.3",
2479 | "on-finished": "2.4.1",
2480 | "range-parser": "~1.2.1",
2481 | "statuses": "2.0.1"
2482 | },
2483 | "engines": {
2484 | "node": ">= 0.8.0"
2485 | }
2486 | },
2487 | "node_modules/send/node_modules/ms": {
2488 | "version": "2.1.3",
2489 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
2490 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
2491 | },
2492 | "node_modules/serve-static": {
2493 | "version": "1.15.0",
2494 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
2495 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
2496 | "dependencies": {
2497 | "encodeurl": "~1.0.2",
2498 | "escape-html": "~1.0.3",
2499 | "parseurl": "~1.3.3",
2500 | "send": "0.18.0"
2501 | },
2502 | "engines": {
2503 | "node": ">= 0.8.0"
2504 | }
2505 | },
2506 | "node_modules/setprototypeof": {
2507 | "version": "1.2.0",
2508 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
2509 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
2510 | },
2511 | "node_modules/shebang-command": {
2512 | "version": "2.0.0",
2513 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
2514 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
2515 | "dev": true,
2516 | "dependencies": {
2517 | "shebang-regex": "^3.0.0"
2518 | },
2519 | "engines": {
2520 | "node": ">=8"
2521 | }
2522 | },
2523 | "node_modules/shebang-regex": {
2524 | "version": "3.0.0",
2525 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
2526 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
2527 | "dev": true,
2528 | "engines": {
2529 | "node": ">=8"
2530 | }
2531 | },
2532 | "node_modules/side-channel": {
2533 | "version": "1.0.4",
2534 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
2535 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
2536 | "dependencies": {
2537 | "call-bind": "^1.0.0",
2538 | "get-intrinsic": "^1.0.2",
2539 | "object-inspect": "^1.9.0"
2540 | },
2541 | "funding": {
2542 | "url": "https://github.com/sponsors/ljharb"
2543 | }
2544 | },
2545 | "node_modules/sift": {
2546 | "version": "16.0.1",
2547 | "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz",
2548 | "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ=="
2549 | },
2550 | "node_modules/simple-update-notifier": {
2551 | "version": "2.0.0",
2552 | "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
2553 | "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
2554 | "dev": true,
2555 | "dependencies": {
2556 | "semver": "^7.5.3"
2557 | },
2558 | "engines": {
2559 | "node": ">=10"
2560 | }
2561 | },
2562 | "node_modules/sparse-bitfield": {
2563 | "version": "3.0.3",
2564 | "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
2565 | "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
2566 | "dependencies": {
2567 | "memory-pager": "^1.0.2"
2568 | }
2569 | },
2570 | "node_modules/statuses": {
2571 | "version": "2.0.1",
2572 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
2573 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
2574 | "engines": {
2575 | "node": ">= 0.8"
2576 | }
2577 | },
2578 | "node_modules/strip-ansi": {
2579 | "version": "6.0.1",
2580 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
2581 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
2582 | "dev": true,
2583 | "dependencies": {
2584 | "ansi-regex": "^5.0.1"
2585 | },
2586 | "engines": {
2587 | "node": ">=8"
2588 | }
2589 | },
2590 | "node_modules/strip-json-comments": {
2591 | "version": "3.1.1",
2592 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
2593 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
2594 | "dev": true,
2595 | "engines": {
2596 | "node": ">=8"
2597 | },
2598 | "funding": {
2599 | "url": "https://github.com/sponsors/sindresorhus"
2600 | }
2601 | },
2602 | "node_modules/supports-color": {
2603 | "version": "7.2.0",
2604 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
2605 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
2606 | "dev": true,
2607 | "dependencies": {
2608 | "has-flag": "^4.0.0"
2609 | },
2610 | "engines": {
2611 | "node": ">=8"
2612 | }
2613 | },
2614 | "node_modules/text-table": {
2615 | "version": "0.2.0",
2616 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
2617 | "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
2618 | "dev": true
2619 | },
2620 | "node_modules/to-regex-range": {
2621 | "version": "5.0.1",
2622 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
2623 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
2624 | "dev": true,
2625 | "dependencies": {
2626 | "is-number": "^7.0.0"
2627 | },
2628 | "engines": {
2629 | "node": ">=8.0"
2630 | }
2631 | },
2632 | "node_modules/toidentifier": {
2633 | "version": "1.0.1",
2634 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
2635 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
2636 | "engines": {
2637 | "node": ">=0.6"
2638 | }
2639 | },
2640 | "node_modules/touch": {
2641 | "version": "3.1.0",
2642 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
2643 | "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
2644 | "dev": true,
2645 | "dependencies": {
2646 | "nopt": "~1.0.10"
2647 | },
2648 | "bin": {
2649 | "nodetouch": "bin/nodetouch.js"
2650 | }
2651 | },
2652 | "node_modules/tr46": {
2653 | "version": "4.1.1",
2654 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz",
2655 | "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==",
2656 | "dependencies": {
2657 | "punycode": "^2.3.0"
2658 | },
2659 | "engines": {
2660 | "node": ">=14"
2661 | }
2662 | },
2663 | "node_modules/type-check": {
2664 | "version": "0.4.0",
2665 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
2666 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
2667 | "dev": true,
2668 | "dependencies": {
2669 | "prelude-ls": "^1.2.1"
2670 | },
2671 | "engines": {
2672 | "node": ">= 0.8.0"
2673 | }
2674 | },
2675 | "node_modules/type-fest": {
2676 | "version": "0.20.2",
2677 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
2678 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
2679 | "dev": true,
2680 | "engines": {
2681 | "node": ">=10"
2682 | },
2683 | "funding": {
2684 | "url": "https://github.com/sponsors/sindresorhus"
2685 | }
2686 | },
2687 | "node_modules/type-is": {
2688 | "version": "1.6.18",
2689 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
2690 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
2691 | "dependencies": {
2692 | "media-typer": "0.3.0",
2693 | "mime-types": "~2.1.24"
2694 | },
2695 | "engines": {
2696 | "node": ">= 0.6"
2697 | }
2698 | },
2699 | "node_modules/uc.micro": {
2700 | "version": "1.0.6",
2701 | "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
2702 | "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
2703 | "dev": true
2704 | },
2705 | "node_modules/undefsafe": {
2706 | "version": "2.0.5",
2707 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
2708 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
2709 | "dev": true
2710 | },
2711 | "node_modules/underscore": {
2712 | "version": "1.13.6",
2713 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
2714 | "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==",
2715 | "dev": true
2716 | },
2717 | "node_modules/unpipe": {
2718 | "version": "1.0.0",
2719 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
2720 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
2721 | "engines": {
2722 | "node": ">= 0.8"
2723 | }
2724 | },
2725 | "node_modules/uri-js": {
2726 | "version": "4.4.1",
2727 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
2728 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
2729 | "dev": true,
2730 | "dependencies": {
2731 | "punycode": "^2.1.0"
2732 | }
2733 | },
2734 | "node_modules/utils-merge": {
2735 | "version": "1.0.1",
2736 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
2737 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
2738 | "engines": {
2739 | "node": ">= 0.4.0"
2740 | }
2741 | },
2742 | "node_modules/vary": {
2743 | "version": "1.1.2",
2744 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
2745 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
2746 | "engines": {
2747 | "node": ">= 0.8"
2748 | }
2749 | },
2750 | "node_modules/webidl-conversions": {
2751 | "version": "7.0.0",
2752 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
2753 | "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
2754 | "engines": {
2755 | "node": ">=12"
2756 | }
2757 | },
2758 | "node_modules/whatwg-url": {
2759 | "version": "13.0.0",
2760 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz",
2761 | "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==",
2762 | "dependencies": {
2763 | "tr46": "^4.1.1",
2764 | "webidl-conversions": "^7.0.0"
2765 | },
2766 | "engines": {
2767 | "node": ">=16"
2768 | }
2769 | },
2770 | "node_modules/which": {
2771 | "version": "2.0.2",
2772 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
2773 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
2774 | "dev": true,
2775 | "dependencies": {
2776 | "isexe": "^2.0.0"
2777 | },
2778 | "bin": {
2779 | "node-which": "bin/node-which"
2780 | },
2781 | "engines": {
2782 | "node": ">= 8"
2783 | }
2784 | },
2785 | "node_modules/wrappy": {
2786 | "version": "1.0.2",
2787 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
2788 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
2789 | "dev": true
2790 | },
2791 | "node_modules/xmlcreate": {
2792 | "version": "2.0.4",
2793 | "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz",
2794 | "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==",
2795 | "dev": true
2796 | },
2797 | "node_modules/yallist": {
2798 | "version": "4.0.0",
2799 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
2800 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
2801 | },
2802 | "node_modules/yocto-queue": {
2803 | "version": "0.1.0",
2804 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
2805 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
2806 | "dev": true,
2807 | "engines": {
2808 | "node": ">=10"
2809 | },
2810 | "funding": {
2811 | "url": "https://github.com/sponsors/sindresorhus"
2812 | }
2813 | }
2814 | }
2815 | }
2816 |
--------------------------------------------------------------------------------