diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 00000000..d7315c6d
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,59 @@
+# Plantilla PR BackEnd TEXT & LINES
+
+---
+
+## Descripción
+
+
+
+---
+
+## Tipo de cambio
+
+- [ ] Corrección de error (cambio no disruptivo que soluciona un problema)
+- [ ] Nueva funcionalidad (cambio no disruptivo que agrega funcionalidad)
+- [ ] Cambio disruptivo (corrección o función que afecta la compatibilidad existente)
+- [ ] Este cambio requiere actualización en la documentación
+- [ ] Cambio mínimo (cambio estructural o visual sin impacto en la lógica principal)
+
+---
+
+## Nueva funcionalidad (si aplica)
+
+- [ ] Controlador
+- [ ] Ruta
+- [ ] Repositorio
+- [ ] Consulta
+- [ ] Mensaje
+- [ ] Middleware
+- [ ] Servicio
+
+Si agregaste otro archivo relevante, indícalo aquí:
+- `ejemploArchivo.js`
+
+---
+
+## ¿Cómo se ha probado?
+
+- [ ] Se probaron manualmente los endpoints con Postman
+- [ ] Pasaron las pruebas unitarias (si aplica)
+- [ ] Se probaron integraciones con otros módulos
+- [ ] No se mostraron errores en consola ni logs
+- [ ] Validado en base de datos que el comportamiento es correcto
+
+---
+
+### Cambios menores
+
+- [ ] Este PR realiza un cambio mínimo que no afecta la lógica del sistema
+- [ ] Se validó manualmente que el cambio no afecta funcionalidades existentes
+- [ ] No se realizaron pruebas automatizadas porque no aplica
+
+---
+
+## Checklist del evaluador:
+
+- [ ] He determinado que el autor cumplió con todos los puntos mencionados
+- [ ] He determinado que los cambios no tienen un impacto negativo en la aplicación
+- [ ] He notificado al autor del PR en caso de dudas o ajustes necesarios
+- [ ] Una vez que acepte el PR, eliminaré la rama correspondiente
\ No newline at end of file
diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml
new file mode 100644
index 00000000..b9819b4b
--- /dev/null
+++ b/.github/workflows/deploy.yaml
@@ -0,0 +1,68 @@
+name: Node.js CI/CD
+
+on:
+ push:
+ branches:
+ - main
+ - staging
+
+jobs:
+ deploy-production:
+ if: github.ref == 'refs/heads/main'
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Setup SSH
+ env:
+ DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
+ SERVER_IP: ${{ secrets.SERVER_IP }}
+ run: |
+ mkdir -p ~/.ssh
+ echo "$DEPLOY_KEY" > ~/.ssh/id_rsa
+ chmod 600 ~/.ssh/id_rsa
+ ssh-keyscan -H $SERVER_IP >> ~/.ssh/known_hosts
+ ssh-keyscan -H github.com >> ~/.ssh/known_hosts
+
+ - name: Deploy to Production
+ env:
+ SERVER_IP: ${{ secrets.SERVER_IP }}
+ PROJECT_PATH: ${{ secrets.PROJECT_PATH_PRODUCTION }}
+ GIT_REPO: ${{ secrets.GIT_REPO }}
+ PM2_PROCESS: ${{ secrets.PM2_PROCESS_PRODUCTION }}
+ run: |
+ ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no ubuntu@$SERVER_IP "
+ cd $PROJECT_PATH &&
+ git checkout main &&
+ git pull origin main &&
+ npm install &&
+ pm2 reload ecosystem-production.config.js --only $PM2_PROCESS
+ "
+
+ deploy-staging:
+ if: github.ref == 'refs/heads/staging'
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Setup SSH
+ env:
+ DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
+ SERVER_IP: ${{ secrets.SERVER_IP }}
+ run: |
+ mkdir -p ~/.ssh
+ echo "$DEPLOY_KEY" > ~/.ssh/id_rsa
+ chmod 600 ~/.ssh/id_rsa
+ ssh-keyscan -H $SERVER_IP >> ~/.ssh/known_hosts
+ ssh-keyscan -H github.com >> ~/.ssh/known_hosts
+
+ - name: Deploy to Staging
+ env:
+ SERVER_IP: ${{ secrets.SERVER_IP }}
+ PROJECT_PATH: ${{ secrets.PROJECT_PATH_STAGING }}
+ GIT_REPO: ${{ secrets.GIT_REPO }}
+ PM2_PROCESS: ${{ secrets.PM2_PROCESS_STAGING }}
+ run: |
+ ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no ubuntu@$SERVER_IP "
+ cd $PROJECT_PATH &&
+ git checkout staging &&
+ git pull origin staging &&
+ npm install &&
+ pm2 reload ecosystem-staging.config.js --only $PM2_PROCESS
+ "
diff --git a/.github/workflows/on-pr.yaml b/.github/workflows/on-pr.yaml
new file mode 100644
index 00000000..8f4801c2
--- /dev/null
+++ b/.github/workflows/on-pr.yaml
@@ -0,0 +1,45 @@
+name: Lint on Pull Request
+
+on:
+ pull_request:
+ branches:
+ - main
+ - staging
+ - develop
+ - MBI-1
+
+jobs:
+ lint:
+ runs-on: ubuntu-22.04
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '22.14'
+
+ - name: Install dependencies
+ run: npm install
+
+ - name: Run Linter
+ run: npm run lint
+ pruebas-automaticas:
+ runs-on: ubuntu-22.04
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '22.14'
+
+ - name: Install dependencies
+ run: npm install
+
+ - name: Run Jest
+ run: npm run test
diff --git a/.gitignore b/.gitignore
index 814d1d97..9d2b5800 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,7 +6,7 @@ yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
-
+.idea
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..13566b81
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/aws.xml b/.idea/aws.xml
new file mode 100644
index 00000000..03f1bb6e
--- /dev/null
+++ b/.idea/aws.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 00000000..6ea3fa32
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 00000000..79ee123c
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
new file mode 100644
index 00000000..913be6d2
--- /dev/null
+++ b/.idea/dataSources.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ mysql.8
+ true
+ com.mysql.cj.jdbc.Driver
+ jdbc:mysql://altertex.cqns2oecgotm.us-east-1.rds.amazonaws.com:3306/Altertex
+ $ProjectFileDir$
+
+
+
\ No newline at end of file
diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml
new file mode 100644
index 00000000..47877842
--- /dev/null
+++ b/.idea/dictionaries/project.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 00000000..26a57286
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml
new file mode 100644
index 00000000..94763096
--- /dev/null
+++ b/.idea/material_theme_project_new.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/prettier.xml b/.idea/prettier.xml
new file mode 100644
index 00000000..60cfc994
--- /dev/null
+++ b/.idea/prettier.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..35eb1ddf
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/webResources.xml b/.idea/webResources.xml
new file mode 100644
index 00000000..2d5e98e8
--- /dev/null
+++ b/.idea/webResources.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 00000000..d45243ca
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,16 @@
+{
+ "printWidth": 100,
+ "tabWidth": 2,
+ "useTabs": false,
+ "semi": true,
+ "singleQuote": true,
+ "quoteProps": "as-needed",
+ "jsxSingleQuote": false,
+ "trailingComma": "es5",
+ "bracketSpacing": true,
+ "bracketSameLine": false,
+ "arrowParens": "always",
+ "proseWrap": "preserve",
+ "endOfLine": "lf",
+ "operatorPosition": "before"
+}
diff --git a/Autenticacion/Controladores/activar2FA.controller.js b/Autenticacion/Controladores/activar2FA.controller.js
new file mode 100644
index 00000000..76a67426
--- /dev/null
+++ b/Autenticacion/Controladores/activar2FA.controller.js
@@ -0,0 +1,48 @@
+const speakeasy = require('speakeasy');
+const qrcode = require('qrcode');
+const db = require('@altertex/util/bd/db');
+
+/**
+ * Controlador que genera el secreto TOTP y QR para activación de Google Authenticator.
+ * Guarda el secreto en la tabla usuarios_2fa.
+ *
+ * @async
+ * @param {object} req - La solicitud HTTP.
+ * @param {object} res - La respuesta HTTP.
+ * @returns {Promise} - Respuesta HTTP con el QR y mensaje de éxito.
+ * @throws {Error} - Si ocurre un error durante la activación.
+ * @throws {Error} - Si ocurre un error durante la activación.
+ *
+ */
+const activar2FA = async (req, res) => {
+ try {
+ const { idUsuario, nombre, correo } = req.body;
+
+ // 1. Generar secreto con nombre legible
+ const secret = speakeasy.generateSecret({
+ name: `Altertex (${nombre} - ${correo})`,
+ });
+
+ // 2. Convertir el secret en código QR (para Google Authenticator)
+ const otpauthURL = secret.otpauth_url;
+ const qrCodeBase64 = await qrcode.toDataURL(otpauthURL);
+
+ // 3. Insertar o actualizar en tabla usuarios_2fa
+ await db.query(`
+ INSERT INTO usuarios_2fa (idUsuario, tiene2FA, secret2FA, puedeEliminarSuperadmins)
+ VALUES (?, ?, ?, ?)
+ ON DUPLICATE KEY UPDATE tiene2FA = VALUES(tiene2FA), secret2FA = VALUES(secret2FA)
+ `, [idUsuario, true, secret.base32, true]);
+
+ // 4. Devolver imagen del QR al frontend
+ res.status(200).json({
+ mensaje: 'Se generó el QR de activación.',
+ qrCode: qrCodeBase64,
+ });
+ } catch (error) {
+ console.error('Error al activar 2FA:', error);
+ res.status(500).json({ mensaje: 'Error al activar autenticación 2FA.' });
+ }
+};
+
+module.exports = { activar2FA};
\ No newline at end of file
diff --git a/Autenticacion/Controladores/cerrarSesion.controller.js b/Autenticacion/Controladores/cerrarSesion.controller.js
new file mode 100644
index 00000000..93cf3874
--- /dev/null
+++ b/Autenticacion/Controladores/cerrarSesion.controller.js
@@ -0,0 +1,46 @@
+const MENSAJES_AUTENTICACION = require('@altertex/util/const/mensajesAutenticacion');
+
+/**
+ * Controlador para el cierre de sesión de un usuario.
+ *
+ * RF78 - Iniciar Sesion - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF78
+ *
+ * @async
+ * @function cerrarSesion
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.cookies - Cookies enviadas con la solicitud.
+ * @param {string} req.cookies.token - Token JWT almacenado en las cookies.
+ * @param {object} res - Objeto de respuesta de Express.
+ *
+ * @returns {Response} Respuesta HTTP con estado:
+ * - 200 si el cierre de sesión es exitoso.
+ * - 400 si no existe una sesión activa (no hay token).
+ * - 500 si ocurre un error en el servidor al intentar cerrar la sesión.
+ *
+ * @throws {Error} Si ocurre un error inesperado durante la operación.
+ */
+exports.cerrarSesion = async (req, res) => {
+ try {
+ const token = req.cookies.token;
+
+ if (!token) {
+ return res
+ .status(MENSAJES_AUTENTICACION.SESION_NO_EXISTENTE.codigo)
+ .json({ mensaje: MENSAJES_AUTENTICACION.SESION_NO_EXISTENTE.mensaje });
+ }
+
+ res.clearCookie('token', {
+ httpOnly: true,
+ secure: true,
+ sameSite: 'None',
+ });
+
+ return res
+ .status(MENSAJES_AUTENTICACION.CIERRE_SESION_EXITOSO.codigo)
+ .json({ mensaje: MENSAJES_AUTENTICACION.CIERRE_SESION_EXITOSO.mensaje });
+ } catch {
+ return res
+ .status(MENSAJES_AUTENTICACION.ERROR_CIERRE_SESION.codigo)
+ .json({ mensaje: MENSAJES_AUTENTICACION.ERROR_CIERRE_SESION.mensaje });
+ }
+};
diff --git a/Autenticacion/Controladores/inicioSesion.controller.js b/Autenticacion/Controladores/inicioSesion.controller.js
new file mode 100644
index 00000000..6476f6b6
--- /dev/null
+++ b/Autenticacion/Controladores/inicioSesion.controller.js
@@ -0,0 +1,102 @@
+const repositorio = require('@altertex/aut/repos/repositorioInicioSesion');
+const bcrypt = require('bcryptjs');
+const jwt = require('jsonwebtoken');
+
+const MENSAJES_AUTENTICACION = require('@altertex/util/const/mensajesAutenticacion');
+
+/**
+ * Controlador para el inicio de sesión de un usuario.
+ *
+ * RF78 - Iniciar Sesion - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF78
+ *
+ * @async
+ * @function inicioSesion
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.body - Cuerpo de la solicitud HTTP.
+ * @param {string} req.body.correo - Correo electrónico del usuario.
+ * @param {string} req.body.contrasenia - Contraseña proporcionada por el usuario.
+ * @param {object} res - Objeto de respuesta de Express.
+ *
+ * @returns {Response} Respuesta HTTP con estado:
+ * - 200 si el inicio de sesión es exitoso, junto con un JWT.
+ * - 400 si faltan campos requeridos o el formato del correo es inválido.
+ * - 401 si las credenciales son incorrectas.
+ * - 500 si ocurre un error en el servidor.
+ *
+ * @throws {Error} Si ocurre un error inesperado durante la operación.
+ */
+exports.inicioSesion = async (req, res) => {
+ const { correo, contrasenia } = req.body;
+
+ const tiempoExpiracion = 8 * 60 * 60 * 1000;
+
+ if (!correo || !contrasenia) {
+ return res
+ .status(MENSAJES_AUTENTICACION.CAMPOS_OBLIGATORIOS.codigo)
+ .json({ mensaje: MENSAJES_AUTENTICACION.CAMPOS_OBLIGATORIOS.mensaje });
+ }
+
+ const formatoCorreoValido = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(correo);
+ if (!formatoCorreoValido) {
+ return res.status(MENSAJES_AUTENTICACION.FORMATO_CORREO_INVALIDO.codigo).json({
+ mensaje: MENSAJES_AUTENTICACION.FORMATO_CORREO_INVALIDO.mensaje,
+ });
+ }
+
+ try {
+ const resultadoQuery = await repositorio.obtenerUsuario(correo);
+
+ const usuario = resultadoQuery.infoUsuario[0];
+ const permisos = resultadoQuery.permisos;
+ const clientesAsociados = resultadoQuery.clientesAsociados;
+
+ if (!usuario) {
+ return res.status(MENSAJES_AUTENTICACION.CREDENCIALES_INVALIDAS.codigo).json({
+ mensaje: MENSAJES_AUTENTICACION.CREDENCIALES_INVALIDAS.mensaje,
+ });
+ }
+
+ const contraCorrecta = await bcrypt.compare(contrasenia, usuario.contrasenia);
+
+ if (!contraCorrecta) {
+ return res.status(MENSAJES_AUTENTICACION.CREDENCIALES_INVALIDAS.codigo).json({
+ mensaje: MENSAJES_AUTENTICACION.CREDENCIALES_INVALIDAS.mensaje,
+ });
+ }
+
+ const token = jwt.sign(
+ {
+ idUsuario: usuario.idUsuario,
+ correo: usuario.correoElectronico,
+ permisos,
+ clientesAsociados,
+ nombre: usuario.nombreCompleto,
+ },
+ process.env.JWT_SECRET,
+ {
+ expiresIn: '8h',
+ },
+ );
+
+ res.cookie('token', token, {
+ httpOnly: true,
+ secure: true,
+ sameSite: 'None',
+ });
+
+ res.cookie('nombreUsuario', usuario.nombreCompleto, {
+ httpOnly: false,
+ secure: true,
+ sameSite: 'None',
+ maxAge: tiempoExpiracion,
+ });
+
+ return res.status(MENSAJES_AUTENTICACION.INICIO_SESION_EXITOSO.codigo).json({
+ mensaje: MENSAJES_AUTENTICACION.INICIO_SESION_EXITOSO.mensaje,
+ });
+ } catch {
+ return res
+ .status(MENSAJES_AUTENTICACION.ERROR_SERVIDOR.codigo)
+ .json({ mensaje: MENSAJES_AUTENTICACION.ERROR_SERVIDOR.mensaje });
+ }
+};
diff --git a/Autenticacion/Controladores/verificar2FA.controller.js b/Autenticacion/Controladores/verificar2FA.controller.js
new file mode 100644
index 00000000..b307996f
--- /dev/null
+++ b/Autenticacion/Controladores/verificar2FA.controller.js
@@ -0,0 +1,62 @@
+// @file verificar2FA.controller.js
+// @description Verifica el código 2FA de Google Authenticator para acciones críticas como eliminar superadmins.
+
+const speakeasy = require('speakeasy'); // Biblioteca para verificar códigos TOTP (2FA)
+const db = require('@altertex/util/bd/db'); // Conexión a la base de datos
+
+/**
+ * Controlador que verifica el código 2FA de Google Authenticator.
+ *
+ * Se utiliza en operaciones críticas (ej. eliminación de Superadmins),
+ * validando el token TOTP generado desde una app de autenticación (como Google Authenticator).
+ *
+ * @async
+ * @function verificar2FA
+ * @param {object} req - Objeto de solicitud HTTP.
+ * @param {number} req.body.idUsuario - ID del usuario que solicita la operación.
+ * @param {string} req.body.codigo - Código TOTP ingresado por el usuario.
+ * @param {object} res - Objeto de respuesta HTTP.
+ * @returns {Promise} - Envía una respuesta JSON con el resultado de la verificación.
+ */
+const verificar2FA = async (req, res) => {
+ try {
+ const { idUsuario, codigo } = req.body;
+
+ // Validación básica de parámetros
+ if (!idUsuario || !codigo) {
+ return res.status(400).json({ mensaje: 'Faltan campos requeridos.' });
+ }
+
+ // Consultar el secreto almacenado para el usuario con 2FA activado
+ const [resultado] = await db.query(
+ 'SELECT secret2FA FROM usuarios_2fa WHERE idUsuario = ? AND tiene2FA = true',
+ [idUsuario]
+ );
+
+ // Verificación de existencia de secreto
+ if (!resultado || resultado.length === 0) {
+ return res.status(403).json({ mensaje: 'No tienes activado 2FA o no estás autorizado.' });
+ }
+
+ const { secret2FA } = resultado[0];
+
+ // Verificación del código TOTP usando el secreto y un margen de 30s
+ const esValido = speakeasy.totp.verify({
+ secret: secret2FA,
+ encoding: 'base32',
+ token: codigo,
+ window: 1,
+ });
+
+ if (!esValido) {
+ return res.status(401).json({ mensaje: 'Código inválido o expirado.' });
+ }
+
+ return res.status(200).json({ mensaje: 'Código verificado correctamente.' });
+ } catch (error) {
+ console.error('Error al verificar 2FA:', error);
+ return res.status(500).json({ mensaje: 'Error al verificar autenticación 2FA.' });
+ }
+};
+
+module.exports = { verificar2FA };
\ No newline at end of file
diff --git a/Autenticacion/Datos/Repositorios/repositorioInicioSesion.js b/Autenticacion/Datos/Repositorios/repositorioInicioSesion.js
new file mode 100644
index 00000000..73feab23
--- /dev/null
+++ b/Autenticacion/Datos/Repositorios/repositorioInicioSesion.js
@@ -0,0 +1,43 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_USUARIOS = require('@altertex/util/const/consultasUsuarios');
+
+/**
+ * Obtiene la información y los permisos de un usuario a partir de su correo electrónico.
+ *
+ * RF78 - Iniciar Sesion - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF78
+ *
+ * @async
+ * @function obtenerUsuario
+ * @param {string} correoElectronico - Correo electrónico del usuario a buscar.
+ *
+ * @returns {Promise} Objeto con la siguiente estructura si se encuentra el usuario:
+ * - { infoUsuario: Array, permisos: Array }
+ * - Retorna un string con un mensaje de error si ocurre un fallo durante la operación.
+ *
+ * @throws {Error} Si no se encuentra el usuario o ocurre un error en la consulta.
+ */
+exports.obtenerUsuario = async (correoElectronico) => {
+ const queryUsuarios = CONSULTAS_USUARIOS.OBTENER_USUARIO;
+ const queryPermisos = CONSULTAS_USUARIOS.OBTENER_PERMISOS;
+ const queryClientesAsociados = CONSULTAS_USUARIOS.OBTENER_CLIENTES_ASOCIADOS;
+
+ try {
+ const usuario = await correrQuery(queryUsuarios, [correoElectronico]);
+ const resultadoPermisos = await correrQuery(queryPermisos, [correoElectronico]);
+ const resultadoClientesAsociados = await correrQuery(queryClientesAsociados, [
+ correoElectronico,
+ ]);
+
+ const resultado = {
+ infoUsuario: usuario,
+ permisos: resultadoPermisos.map((objetosPermisos) => objetosPermisos.nombre),
+ clientesAsociados: resultadoClientesAsociados.map(
+ (objetosClientes) => objetosClientes.idCliente
+ ),
+ };
+
+ return resultado;
+ } catch {
+ return `Error obteniendo usuario`;
+ }
+};
diff --git a/Autenticacion/Rutas/RutasIndividuales/activar2FA.routes.js b/Autenticacion/Rutas/RutasIndividuales/activar2FA.routes.js
new file mode 100644
index 00000000..c074cd09
--- /dev/null
+++ b/Autenticacion/Rutas/RutasIndividuales/activar2FA.routes.js
@@ -0,0 +1,111 @@
+const express = require('express');
+const ruteador = express.Router();
+
+const controlador = require('@altertex/aut/ctrl/activar2FA.controller');
+
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * RF## - Activar 2FA para Superadmin
+ */
+
+/**
+ * @swagger
+ * /api/seguridad/superadmin/activar-2fa:
+ * post:
+ * summary: Activa autenticación 2FA para un Superadmin autorizado.
+ * tags: [Seguridad]
+ * security:
+ * - ApiKeyAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * required:
+ * - idUsuario
+ * - nombre
+ * - correo
+ * properties:
+ * idUsuario:
+ * type: integer
+ * example: 1
+ * nombre:
+ * type: string
+ * example: Maria González
+ * correo:
+ * type: string
+ * format: email
+ * example: maria.gonzalez@example.com
+ * responses:
+ * 200:
+ * description: 2FA activado exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Se generó el QR de activación.
+ * qrCode:
+ * type: string
+ * format: byte
+ * example: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
+ * 400:
+ * description: Solicitud incorrecta.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error al activar autenticación 2FA.
+ * 401:
+ * description: Token no autorizado.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Token no autorizado.
+ * 403:
+ * description: Usuario no autorizado para activar 2FA.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Usuario no autorizado para activar 2FA.
+ * 500:
+ * description: Error al generar el secreto.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error al generar el secreto.
+ */
+
+ruteador.post(
+ RUTAS.AUTENTICACION.ACTIVAR_2FA,
+ revisarApiKey(),
+ autorizarToken,
+ verificarPermisos(PERMISOS.ACTIVAR_2FA_SUPERADMIN),
+ controlador.activar2FA
+);
+
+module.exports = ruteador;
\ No newline at end of file
diff --git a/Autenticacion/Rutas/RutasIndividuales/autenticacionSesion.routes.js b/Autenticacion/Rutas/RutasIndividuales/autenticacionSesion.routes.js
new file mode 100644
index 00000000..83982e49
--- /dev/null
+++ b/Autenticacion/Rutas/RutasIndividuales/autenticacionSesion.routes.js
@@ -0,0 +1,63 @@
+const express = require('express');
+const ruteador = express.Router();
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/autenticacion/autenticar:
+ * get:
+ * summary: Obtiene los datos del usuario autenticado mediante un token JWT.
+ * tags:
+ * - Autenticación
+ * security:
+ * - ApiKeyAuth: [] # Protegido por API key
+ * responses:
+ * 200:
+ * description: Usuario autenticado correctamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * user:
+ * type: object
+ * example:
+ * correo: usuario@correo.com
+ * permisos:
+ * - ADMIN
+ * - EDITOR
+ * 401:
+ * description: Token no proporcionado, expirado o inválido.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Token no proporcionado o inválido.
+ * 500:
+ * description: Error al validar el token.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error interno al validar el token.
+ */
+
+ruteador.get(
+ RUTAS.AUTENTICACION.USUARIO_AUTENTICADO,
+ revisarApiKey(),
+ autorizarToken,
+ (req, res) => {
+ res.json({ user: req.user });
+ }
+);
+
+module.exports = ruteador;
diff --git a/Autenticacion/Rutas/RutasIndividuales/cerrarSesion.routes.js b/Autenticacion/Rutas/RutasIndividuales/cerrarSesion.routes.js
new file mode 100644
index 00000000..7e49736d
--- /dev/null
+++ b/Autenticacion/Rutas/RutasIndividuales/cerrarSesion.routes.js
@@ -0,0 +1,56 @@
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/aut/ctrl/cerrarSesion.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * RF78 - Iniciar Sesion - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF78
+ */
+
+/**
+ * @swagger
+ * /api/autenticacion/cerrar-sesion:
+ * post:
+ * summary: Cierra la sesión del usuario actual eliminando la cookie con el token.
+ * tags:
+ * - Autenticación
+ * security:
+ * - ApiKeyAuth: [] # Si usas revisión de API key
+ * responses:
+ * 200:
+ * description: Cierre de sesión exitoso.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Cierre de sesión exitoso.
+ * 400:
+ * description: No existe una sesión activa (no se encontró token).
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No hay sesión activa.
+ * 500:
+ * description: Error al intentar cerrar sesión.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error en el servidor al cerrar sesión.
+ */
+
+ruteador.post(RUTAS.AUTENTICACION.CERRAR_SESION, revisarApiKey(), controlador.cerrarSesion);
+
+module.exports = ruteador;
diff --git a/Autenticacion/Rutas/RutasIndividuales/inicioSesion.routes.js b/Autenticacion/Rutas/RutasIndividuales/inicioSesion.routes.js
new file mode 100644
index 00000000..e72e6541
--- /dev/null
+++ b/Autenticacion/Rutas/RutasIndividuales/inicioSesion.routes.js
@@ -0,0 +1,89 @@
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/aut/ctrl/inicioSesion.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+
+
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * RF78 - Iniciar Sesion - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF78
+ */
+
+/**
+ * @swagger
+ * /api/autenticacion/iniciar-sesion:
+ * post:
+ * summary: Inicia sesión con correo y contraseña.
+ * tags:
+ * - Autenticación
+ * security:
+ * - ApiKeyAuth: [] # Si estás usando autenticación por API key
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * required:
+ * - correo
+ * - contrasenia
+ * properties:
+ * correo:
+ * type: string
+ * format: email
+ * example: maria.gonzalez@example.com
+ * contrasenia:
+ * type: string
+ * example: hola
+ * responses:
+ * 200:
+ * description: Inicio de sesión exitoso.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Inicio de sesión exitoso.
+ * 400:
+ * description: Faltan campos requeridos o formato inválido.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: El correo y la contraseña son obligatorios.
+ * 401:
+ * description: Credenciales inválidas.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Credenciales incorrectas.
+ * 500:
+ * description: Error interno del servidor.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error en el servidor.
+ */
+ruteador.post(
+ RUTAS.AUTENTICACION.INICIO_SESION,
+ validarYSanitizar,
+ revisarApiKey(),
+ controlador.inicioSesion,
+);
+
+module.exports = ruteador;
diff --git a/Autenticacion/Rutas/RutasIndividuales/verificar2FA.routes.js b/Autenticacion/Rutas/RutasIndividuales/verificar2FA.routes.js
new file mode 100644
index 00000000..c267e191
--- /dev/null
+++ b/Autenticacion/Rutas/RutasIndividuales/verificar2FA.routes.js
@@ -0,0 +1,102 @@
+const express = require('express');
+const ruteador = express.Router();
+
+const controlador = require('@altertex/aut/ctrl/verificar2FA.controller');
+
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * RF## - Verificar 2FA para Superadmin
+ */
+
+/**
+ * @swagger
+ * /api/seguridad/superadmin/verificar-2fa:
+ * post:
+ * summary: Verifica el código 2FA proporcionado por el Superadmin.
+ * tags: [Seguridad]
+ * security:
+ * - ApiKeyAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * required:
+ * - idUsuario
+ * - codigo
+ * properties:
+ * idUsuario:
+ * type: integer
+ * example: 1
+ * codigo:
+ * type: string
+ * example: 123456
+ * responses:
+ * 200:
+ * description: Código 2FA verificado correctamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Autenticación 2FA exitosa.
+ * 400:
+ * description: Código inválido o ya expirado.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Código 2FA inválido.
+ * 401:
+ * description: Token no autorizado.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Token no autorizado.
+ * 403:
+ * description: Usuario no autorizado para verificar 2FA.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Usuario no autorizado para verificar 2FA.
+ * 500:
+ * description: Error al verificar el código 2FA.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error interno al verificar el código.
+ */
+
+ruteador.post(
+ RUTAS.AUTENTICACION.VERIFICAR_2FA,
+ revisarApiKey(),
+ autorizarToken,
+ verificarPermisos(PERMISOS.VERIFICAR_2FA_SUPERADMIN),
+ controlador.verificar2FA
+);
+
+module.exports = ruteador;
\ No newline at end of file
diff --git a/Autenticacion/Rutas/indexAutenticacion.routes.js b/Autenticacion/Rutas/indexAutenticacion.routes.js
new file mode 100644
index 00000000..69bd11ad
--- /dev/null
+++ b/Autenticacion/Rutas/indexAutenticacion.routes.js
@@ -0,0 +1,19 @@
+const express = require("express");
+const ruteador = express.Router();
+const rutasAutenticacionSesion = require("@altertex/aut/rutasInd/autenticacionSesion.routes");
+const rutasInicioSesion = require("@altertex/aut/rutasInd/inicioSesion.routes");
+const rutasCerrarSesion = require("@altertex/aut/rutasInd/cerrarSesion.routes");
+const rutasVerificar2FA = require('@altertex/aut/rutasInd/verificar2FA.routes');
+const rutasActivar2FA = require('@altertex/aut/rutasInd/activar2FA.routes');
+
+const RUTAS = require("@altertex/util/const/rutas");
+
+ruteador.use(RUTAS.AUTENTICACION.BASE, rutasAutenticacionSesion);
+
+//RF78 - Iniciar Sesion - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF78
+ruteador.use(RUTAS.AUTENTICACION.BASE, rutasInicioSesion);
+ruteador.use(RUTAS.AUTENTICACION.BASE, rutasCerrarSesion);
+ruteador.use(RUTAS.AUTENTICACION.BASE, rutasVerificar2FA);
+ruteador.use(RUTAS.AUTENTICACION.BASE, rutasActivar2FA);
+
+module.exports = ruteador;
diff --git a/CRON_JOBS/Controladores/actualizarCuotaSet.controller.js b/CRON_JOBS/Controladores/actualizarCuotaSet.controller.js
new file mode 100644
index 00000000..ae9b1830
--- /dev/null
+++ b/CRON_JOBS/Controladores/actualizarCuotaSet.controller.js
@@ -0,0 +1,32 @@
+/**
+ *
+ * RF31 - Crear Cuotas - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF31
+ *
+ * @file Cron job que se ejecuta cada 5 minutos para obtener información de los cuota sets.
+ *
+ * @module cron/actualizarCuotaSets
+ *
+ * @requires node-cron
+ * @requires @altertex/CRON/repos/actualizarCuotaSetsRepositorio
+ *
+ * @description
+ * Este cron job se ejecuta automáticamente cada 5 minutos.
+ * Llama al repositorio `obtenerCuota` para realizar operaciones sobre los cuota sets.
+ * Si ocurre un error durante la ejecución, se captura y se muestra en consola.
+ */
+
+const cron = require('node-cron');
+const repositorio = require('@altertex/CRON/repos/actualizarCuotaSetsRepositorio');
+
+/**
+ * Tarea programada que se ejecuta a las 00:00.
+ * Ejecuta `repositorio.obtenerCuota` para actualizar información relacionada con los cuota sets.
+ */
+module.exports = cron.schedule('0 0 * * *', async () => {
+ try {
+ const resultado = await repositorio.obtenerCuota();
+ console.log('Resultado del cron:', resultado);
+ } catch (error) {
+ console.error('Error en el cron:', error);
+ }
+});
diff --git a/CRON_JOBS/Datos/Repositorios/actualizarCuotaSetsRepositorio.js b/CRON_JOBS/Datos/Repositorios/actualizarCuotaSetsRepositorio.js
new file mode 100644
index 00000000..0a3fee35
--- /dev/null
+++ b/CRON_JOBS/Datos/Repositorios/actualizarCuotaSetsRepositorio.js
@@ -0,0 +1,56 @@
+/**
+ *
+ * RF31 - Crear Cuotas - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF31
+ *
+ * @file Función encargada de actualizar los límites y fechas de los cuota sets.
+ *
+ * @module repositorio/obtenerCuota
+ *
+ * @requires @altertex/util/bd/db
+ * @requires @altertex/util/const/consultasCuotas
+ */
+
+const db = require('@altertex/util/bd/db');
+const QUERY = require('@altertex/util/const/consultasCuotas');
+
+/**
+ * Actualiza los límites de productos de los cuota sets y sus fechas de última actualización.
+ *
+ * - Primero intenta resetear los límites (`QUERY.RESETEAR_LIMITES`).
+ * - Si se realiza al menos una modificación, actualiza las fechas (`QUERY.ACTUALIZAR_FECHAS`).
+ * - Si no se modifica ninguna fila, la transacción es revertida.
+ *
+ * @async
+ * @function
+ * @returns {Promise} Resultado de la operación. Puede ser un mensaje de éxito o de error.
+ *
+ * @throws {Error} Si ocurre un fallo en la transacción de base de datos.
+ */
+exports.obtenerCuota = async () => {
+ const conexion = await db.getConnection();
+
+ try {
+ await conexion.beginTransaction();
+
+ const [resultadoReseteo] = await conexion.execute(QUERY.RESETEAR_LIMITES);
+
+ if (resultadoReseteo.changedRows === 0) {
+ await conexion.rollback();
+ return {
+ error: 'Ninguna columna se actualizo. No se actualizara la fecha.',
+ };
+ }
+
+ await conexion.execute(QUERY.ACTUALIZAR_FECHAS);
+
+ await conexion.commit();
+
+ return { exito: 'Actualizacion exitosa' };
+ } catch (error) {
+ await conexion.rollback();
+ console.error('Transacción fallida: ', error);
+ throw new Error('Error actualizando cuota sets');
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
\ No newline at end of file
diff --git a/Categorias/Controladores/actualizarCategoria.controller.js b/Categorias/Controladores/actualizarCategoria.controller.js
new file mode 100644
index 00000000..8138e24d
--- /dev/null
+++ b/Categorias/Controladores/actualizarCategoria.controller.js
@@ -0,0 +1,44 @@
+const { actualizarCategoria } = require('@altertex/cat/repos/repositorioActualizarCategorias');
+const MENSAJES = require('@altertex/util/const/mensajesCategorias');
+
+/**
+ * RF49 - Actualizar categoría de productos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF49
+ *
+ * @param {express.Request} req
+ * @param {express.Response} res
+ * @returns {Promise}
+ */
+exports.actualizarCategoria = async (req, res) => {
+ try {
+ const { idCategoria } = req.params;
+ const { nombreCategoria, descripcion, productos } = req.body;
+
+ if (!idCategoria) {
+ return res.status(400).json(MENSAJES.CATEGORIA_NO_ENCONTRADA);
+ }
+
+ if (!nombreCategoria || typeof nombreCategoria !== 'string' || nombreCategoria.trim() === '') {
+ return res.status(400).json(MENSAJES.NOMBRE_CATEGORIA_INVALIDO);
+ }
+
+ if (!Array.isArray(productos)) {
+ return res.status(400).json({
+ codigo: 400,
+ mensaje: 'El campo productos debe ser un arreglo.',
+ });
+ }
+
+ if (descripcion && typeof descripcion !== 'string') {
+ return res.status(400).json(MENSAJES.DESCRIPCION_INVALIDA);
+ }
+
+ await actualizarCategoria({ idCategoria, nombreCategoria, descripcion, productos });
+
+ return res.status(200).json({
+ codigo: 200,
+ mensaje: 'Categoría actualizada correctamente.',
+ });
+ } catch {
+ return res.status(500).json(MENSAJES.ERROR_CREAR_CATEGORIA);
+ }
+};
\ No newline at end of file
diff --git a/Categorias/Controladores/consultarDetalleCategoria.controller.js b/Categorias/Controladores/consultarDetalleCategoria.controller.js
new file mode 100644
index 00000000..1bcd4163
--- /dev/null
+++ b/Categorias/Controladores/consultarDetalleCategoria.controller.js
@@ -0,0 +1,41 @@
+const repositorio = require('@altertex/cat/repos/repositorioLeerDetalleCategoria');
+const MENSAJES_CATEGORIAS = require('@altertex/util/const/mensajesCategorias');
+
+/**
+ * Consulta el detalle de una categoría de productos, incluyendo sus productos asociados.
+ *
+ * @function
+ * @async
+ * @param {Express.Request} req - Objeto de solicitud HTTP con `req.params.idCategoria`.
+ * @param {Express.Response} res - Objeto de respuesta HTTP para enviar el resultado.
+ *
+ * @returns {Promise} Devuelve una respuesta HTTP con el detalle de la categoría o un mensaje de error.
+ *
+ * @description
+ * Implementa el RF48: Leer categoría de productos.
+ * Si no se encuentra la categoría, devuelve código 404.
+ * Si ocurre un error inesperado, devuelve código 500.
+ *
+ * @see [RF48 - Documentación de requisitos](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF48)
+ */
+exports.consultarDetalleCategoria = async (req, res) => {
+ const idCategoria = parseInt(req.params.idCategoria);
+
+ try {
+ const resultado = await repositorio.leerDetalleCategoria(idCategoria);
+
+ if (!resultado) {
+ return res
+ .status(MENSAJES_CATEGORIAS.CATEGORIA_NO_ENCONTRADA.codigo)
+ .json({ mensaje: MENSAJES_CATEGORIAS.CATEGORIA_NO_ENCONTRADA.mensaje });
+ }
+
+ return res
+ .status(MENSAJES_CATEGORIAS.CATEGORIA_OBTENIDA.codigo)
+ .json({ mensaje: MENSAJES_CATEGORIAS.CATEGORIA_OBTENIDA.mensaje, categoria: resultado });
+ } catch {
+ return res
+ .status(MENSAJES_CATEGORIAS.ERROR_OBTENER_CATEGORIA.codigo)
+ .json({ mensaje: MENSAJES_CATEGORIAS.ERROR_OBTENER_CATEGORIA.mensaje });
+ }
+};
\ No newline at end of file
diff --git a/Categorias/Controladores/consultarListaCategorias.controller.js b/Categorias/Controladores/consultarListaCategorias.controller.js
new file mode 100644
index 00000000..5a5b00d7
--- /dev/null
+++ b/Categorias/Controladores/consultarListaCategorias.controller.js
@@ -0,0 +1,37 @@
+const repositorio = require('@altertex/cat/repos/repositorioConsultarListaCategorias');
+const MENSAJES_CATEGORIAS = require('@altertex/util/const/mensajesCategorias');
+
+/**
+ * Consulta la lista de categorías asociadas a un cliente.
+ *
+ * @function
+ * @async
+ * @param {Express.Request} req - Objeto de solicitud HTTP. Debe contener `req.user.clienteSeleccionado` como ID del cliente autenticado.
+ * @param {Express.Response} res - Objeto de respuesta HTTP para enviar los resultados.
+ *
+ * @returns {Promise} Devuelve una respuesta HTTP con la lista de categorías o un mensaje de error.
+ *
+ * @see [RF47 - Documentación de requisitos](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF47)
+ */
+exports.consultarListaCategorias = async (req, res) => {
+ const idCliente = parseInt(req.user.clienteSeleccionado);
+
+ try {
+ const resultados = await repositorio.consultarListaCategorias(idCliente);
+
+ if (!resultados || resultados.length === 0) {
+ return res
+ .status(MENSAJES_CATEGORIAS.CATEGORIAS_NO_ENCONTRADAS.codigo)
+ .json({ mensaje: MENSAJES_CATEGORIAS.CATEGORIAS_NO_ENCONTRADAS.mensaje });
+ }
+
+ return res.status(MENSAJES_CATEGORIAS.LISTA_CATEGORIAS_OBTENIDA.codigo).json({
+ mensaje: MENSAJES_CATEGORIAS.LISTA_CATEGORIAS_OBTENIDA.mensaje,
+ listaCategoria: resultados,
+ });
+ } catch {
+ return res
+ .status(MENSAJES_CATEGORIAS.ERROR_OBTENER_CATEGORIAS.codigo)
+ .json({ mensaje: MENSAJES_CATEGORIAS.ERROR_OBTENER_CATEGORIAS.mensaje });
+ }
+};
\ No newline at end of file
diff --git a/Categorias/Controladores/crearCategoria.controller.js b/Categorias/Controladores/crearCategoria.controller.js
new file mode 100644
index 00000000..3fef1073
--- /dev/null
+++ b/Categorias/Controladores/crearCategoria.controller.js
@@ -0,0 +1,40 @@
+// RF[46] Crear categoria - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF46]
+
+const MENSAJES = require('@altertex/util/const/mensajesCategorias');
+const repositorio = require('@altertex/cat/repos/repositorioCrearCategoria');
+
+/**
+ * Crea una nueva categoría y la guarda en la base de datos.
+ *
+ * @function
+ * @async
+ * @param {Express.Request} req - Objeto de solicitud HTTP, debe contener `nombreCategoria` y `productos` en `req.body`.
+ * @param {Express.Response} res - Objeto de respuesta HTTP para enviar el resultado de la operación.
+ *
+ * @returns {Promise} Envía una respuesta HTTP con el resultado de la operación.
+ *
+ * @description
+ * Este endpoint implementa el RF[46] para la creación de una categoría con productos asociados.
+ * Valida que los datos requeridos estén presentes y maneja errores de forma controlada.
+ */
+exports.crearCategoria = async (req, res) => {
+ const categoria = req.body.categoria;
+
+ if (!categoria.nombreCategoria || !categoria.productos) {
+ return res
+ .status(MENSAJES.NOMBRE_CATEGORIA_INVALIDO.codigo)
+ .json({ mensaje: MENSAJES.NOMBRE_CATEGORIA_INVALIDO.mensaje });
+ }
+
+ try {
+ await repositorio.crearCategoria(categoria);
+
+ return res
+ .status(MENSAJES.CATEGORIA_CREADA.codigo)
+ .json({ exito: MENSAJES.CATEGORIA_CREADA.mensaje });
+ } catch (errorRepo) {
+ return res
+ .status(MENSAJES.ERROR_CREAR_CATEGORIA.codigo)
+ .json({ mensaje: errorRepo.message });
+ }
+};
diff --git a/Categorias/Controladores/eliminarCategoria.controller.js b/Categorias/Controladores/eliminarCategoria.controller.js
new file mode 100644
index 00000000..acfccdeb
--- /dev/null
+++ b/Categorias/Controladores/eliminarCategoria.controller.js
@@ -0,0 +1,49 @@
+const repositorio = require('@altertex/cat/repos/repositorioEliminarCategoria');
+const MENSAJES_CATEGORIAS = require('@altertex/util/const/mensajesCategorias');
+
+/**
+ * Controlador para eliminar una categoría de productos.
+ * RF[50] - Elimina categoría de productos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF50
+ *
+ * @async
+ * @function eliminarCategoria
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.body - Cuerpo de la solicitud HTTP.
+ * @param {number[]} req.body.idsCategoria - Array de IDs numéricos de las categorías a eliminar.
+ * @param {object} res - Objeto de respuesta de Express.
+ * @returns {Promise} Respuesta HTTP con estado:
+ * - 200 si las categorías fueron eliminadas correctamente.
+ * - 404 si no se encontraron las categorías.
+ * - 500 si ocurre un error en el servidor.
+ * @throws {Error} Si ocurre un error durante la eliminación.
+ */
+exports.eliminarCategoria = async (req, res) => {
+ try {
+ const idsCategorias = req.body.idsCategoria;
+
+ if (!Array.isArray(idsCategorias) || idsCategorias.length === 0) {
+ return res.status(MENSAJES_CATEGORIAS.CATEGORIA_NO_ENCONTRADA.codigo).json({
+ mensaje: MENSAJES_CATEGORIAS.CATEGORIA_NO_ENCONTRADA.mensaje,
+ });
+ }
+
+ await Promise.all(
+ idsCategorias.map(async (idCategoria) => {
+ await repositorio.eliminarProductoCategoria(idCategoria);
+ const resultadoCategoria = await repositorio.eliminarCategoria(idCategoria);
+
+ if (resultadoCategoria.affectedRows === 0) {
+ throw new Error(`Categoría con ID ${idCategoria} no encontrada`);
+ }
+ })
+ );
+
+ return res.status(MENSAJES_CATEGORIAS.CATEGORIA_ELIMINADA.codigo).json({
+ mensaje: MENSAJES_CATEGORIAS.CATEGORIA_ELIMINADA.mensaje,
+ });
+ } catch {
+ return res.status(MENSAJES_CATEGORIAS.ERROR_ELIMINAR_CATEGORIA.codigo).json({
+ mensaje: MENSAJES_CATEGORIAS.ERROR_ELIMINAR_CATEGORIA.mensaje,
+ });
+ }
+};
diff --git a/Categorias/Datos/Repositorios/repositorioActualizarCategorias.js b/Categorias/Datos/Repositorios/repositorioActualizarCategorias.js
new file mode 100644
index 00000000..b3c72b05
--- /dev/null
+++ b/Categorias/Datos/Repositorios/repositorioActualizarCategorias.js
@@ -0,0 +1,22 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS = require('@altertex/util/const/consultasCategorias');
+
+/**
+ * Actualiza el nombre, descripción y productos de una categoría.
+ *
+ * @param {object} categoria - Objeto con los datos de la categoría.
+ * @param {number} categoria.idCategoria - ID de la categoría a actualizar.
+ * @param {string} categoria.nombreCategoria - Nuevo nombre de la categoría.
+ * @param {string} categoria.descripcion - Nueva descripción.
+ * @param {number[]} categoria.productos - IDs de productos asociados.
+ * @returns {Promise}
+ */
+exports.actualizarCategoria = async ({ idCategoria, nombreCategoria, descripcion, productos }) => {
+ await correrQuery(CONSULTAS.ACTUALIZAR_CATEGORIA, [nombreCategoria, descripcion, idCategoria]);
+ await correrQuery(CONSULTAS.ELIMINAR_PRODUCTOS_CATEGORIA, [idCategoria]);
+
+ if (productos && productos.length > 0) {
+ const valores = productos.map((idProd) => [idCategoria, idProd]);
+ await correrQuery(CONSULTAS.ASIGNAR_PRODUCTOS_A_CATEGORIA, [valores]);
+ }
+};
\ No newline at end of file
diff --git a/Categorias/Datos/Repositorios/repositorioConsultarListaCategorias.js b/Categorias/Datos/Repositorios/repositorioConsultarListaCategorias.js
new file mode 100644
index 00000000..27d5a8df
--- /dev/null
+++ b/Categorias/Datos/Repositorios/repositorioConsultarListaCategorias.js
@@ -0,0 +1,19 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_CATEGORIAS = require('@altertex/util/const/consultasCategorias');
+
+/**
+ * Consulta la lista de categorías y sus productos asociadas a un cliente específico.
+ *
+ * @function
+ * @async
+ * @param {number} idCliente - ID del cliente cuyas categorías se desean consultar.
+ * @returns {Promise>} Arreglo con las categorías encontradas, cada una con sus productos asociados.
+ *
+ * @throws {Error} Lanza un error si ocurre un fallo al ejecutar la consulta a la base de datos.
+ *
+ * @see [RF47 - Documentación de requisitos](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF47)
+ */
+exports.consultarListaCategorias = (idCliente) => {
+ const query = CONSULTAS_CATEGORIAS.OBTENER_CATEGORIAS_CON_PRODUCTOS;
+ return correrQuery(query, [idCliente]);
+};
\ No newline at end of file
diff --git a/Categorias/Datos/Repositorios/repositorioCrearCategoria.js b/Categorias/Datos/Repositorios/repositorioCrearCategoria.js
new file mode 100644
index 00000000..46ec5fec
--- /dev/null
+++ b/Categorias/Datos/Repositorios/repositorioCrearCategoria.js
@@ -0,0 +1,95 @@
+const CONSULTA = require('@altertex/util/const/consultasCategorias');
+const db = require('@altertex/util/bd/db');
+const MENSAJES = require('@altertex/util/const/mensajesCategorias');
+
+
+/**
+ * Crea una nueva categoría y la asocia con productos válidos en la base de datos.
+ *
+ * Este método valida que los parámetros sean correctos, verifica que el nombre
+ * de la categoría no esté duplicado, comprueba que los productos existan en la base de datos,
+ * y finalmente inserta la nueva categoría y sus asociaciones en la tabla correspondiente.
+ *
+ * @async
+ * @function
+ * @param {object} categoria - Objeto con los datos de la categoría a crear.
+ * @param {string} categoria.nombreCategoria - Nombre de la categoría (obligatorio).
+ * @param {string} [categoria.descripcion] - Descripción opcional de la categoría.
+ * @param {Array} categoria.productos - Lista de productos a asociar.
+ * @param {number} categoria.productos[].idProducto - ID del producto a asociar (obligatorio).
+ *
+ * @returns {Promise} El ID de la nueva categoría creada.
+ *
+ * @throws {Error} Si faltan parámetros, si el nombre es inválido o ya existe,
+ * o si uno o más productos no existen en la base de datos.
+ *
+ * @example
+ * const nuevaCategoriaId = await crearCategoria({
+ * nombreCategoria: 'Promociones',
+ * descripcion: 'Categoría para productos en descuento',
+ * productos: [{ idProducto: 1 }, { idProducto: 2 }]
+ * });
+ */
+exports.crearCategoria = async (categoria) => {
+ const conexion = await db.getConnection();
+
+ try {
+ await conexion.beginTransaction();
+
+ if (!categoria) {
+ throw new Error(MENSAJES.PARAMETROS_INVALIDOS.mensaje);
+ }
+
+ const { nombreCategoria, descripcion, productos } = categoria;
+
+ if (!nombreCategoria || typeof nombreCategoria !== 'string') {
+ throw new Error(MENSAJES.NOMBRE_CATEGORIA_INVALIDO.mensaje);
+ }
+
+ if (!productos || !Array.isArray(productos) || productos.length === 0) {
+ throw new Error(MENSAJES.PARAMETROS_INVALIDOS.mensaje);
+ }
+
+ const [categoriasExistentes] = await conexion.execute(
+ CONSULTA.CATEGORIA_EXISTENTE_POR_NOMBRE,
+ [nombreCategoria],
+ );
+
+ if (categoriasExistentes.length > 0) {
+ throw new Error(`Ya existe una categoría con ese nombre.`);
+ }
+
+ const idsProductos = productos.map(producto => producto.idProducto);
+ const [productosValidos] = await conexion.query(
+ CONSULTA.PRODUCTOS_EXISTENTES_POR_IDS,
+ [idsProductos],
+ );
+
+ const idsValidos = productosValidos.map(producto => producto.idProducto);
+ const idsInvalidos = idsProductos.filter(id => !idsValidos.includes(id));
+
+ if (idsInvalidos.length > 0) {
+ throw new Error(`Productos inválidos: ${idsInvalidos.join(', ')}`);
+ }
+
+ const [resultado] = await conexion.execute(CONSULTA.CREAR_CATEGORIAS, [
+ nombreCategoria,
+ descripcion,
+ ]);
+
+ const categoriaId = resultado.insertId;
+
+ for (const item of productos) {
+ await conexion.execute(CONSULTA.CREAR_CATEGORIA_PRODUCTOS, [categoriaId, item.idProducto]);
+ }
+
+ await conexion.commit();
+
+ return categoriaId;
+ } catch (error) {
+ if (conexion) await conexion.rollback();
+ throw error;
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
diff --git a/Categorias/Datos/Repositorios/repositorioEliminarCategoria.js b/Categorias/Datos/Repositorios/repositorioEliminarCategoria.js
new file mode 100644
index 00000000..c41bb34a
--- /dev/null
+++ b/Categorias/Datos/Repositorios/repositorioEliminarCategoria.js
@@ -0,0 +1,40 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_CATEGORIAS = require('@altertex/util/const/consultasCategorias');
+
+/**
+ * Elimina la relación entre productos y una categoría.
+ *
+ * @async
+ * @function eliminarProductoCategoria
+ * @param {number} idCategoria - ID de la categoría a desvincular de productos.
+ * @returns {Promise} Objeto de resultado de la operación MySQL (por ejemplo, `affectedRows`).
+ * @throws {Error} Si ocurre un error durante la ejecución del query para eliminar la relación.
+ */
+exports.eliminarProductoCategoria = async (idCategoria) => {
+ const query = CONSULTAS_CATEGORIAS.ELIMINAR_CATEGORIA_PRODUCTO;
+ try {
+ const resultado = await correrQuery(query, [idCategoria]);
+ return resultado;
+ } catch {
+ throw new Error('Error eliminando el producto enlazado a la categoria');
+ }
+};
+
+/**
+ * Elimina una categoría de la base de datos.
+ *
+ * @async
+ * @function eliminarCategoria
+ * @param {number} idCategoria - ID de la categoría a eliminar.
+ * @returns {Promise<{affectedRows: number}>} Resultado de la operación con el número de filas afectadas.
+ * @throws {Error} Si ocurre un error durante la operación.
+ */
+exports.eliminarCategoria = async (idCategoria) => {
+ const query = CONSULTAS_CATEGORIAS.ELIMINAR_CATEGORIA;
+ try {
+ const resultado = await correrQuery(query, [idCategoria]);
+ return resultado;
+ } catch {
+ throw new Error('Error eliminando categorias.');
+ }
+};
diff --git a/Categorias/Datos/Repositorios/repositorioLeerDetalleCategoria.js b/Categorias/Datos/Repositorios/repositorioLeerDetalleCategoria.js
new file mode 100644
index 00000000..63b0ca0e
--- /dev/null
+++ b/Categorias/Datos/Repositorios/repositorioLeerDetalleCategoria.js
@@ -0,0 +1,35 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS = require('@altertex/util/const/consultasCategorias');
+
+/**
+ * Consulta el detalle de una categoría y sus productos asociados.
+ *
+ * @param {number} idCategoria - ID de la categoría a consultar.
+ * @returns {Promise} Objeto con la información de la categoría y sus productos, o null si no existe.
+ *
+ * @throws {Error} Si ocurre un error al ejecutar la consulta.
+ *
+ * @see [RF48 - Documentación de requisitos](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF48)
+ */
+exports.leerDetalleCategoria = async (idCategoria) => {
+ const query = CONSULTAS.LEER_DETALLE_CATEGORIA;
+ const resultados = await correrQuery(query, [idCategoria]);
+
+ if (!resultados || resultados.length === 0) return null;
+
+ const { nombreCategoria, descripcion } = resultados[0];
+
+ const productos = resultados
+ .filter(resul => resul.idProducto !== null)
+ .map(produc => ({
+ idProducto: produc.idProducto,
+ nombreComun: produc.nombreComun,
+ }));
+
+ return {
+ idCategoria,
+ nombreCategoria,
+ descripcion,
+ productos,
+ };
+};
\ No newline at end of file
diff --git a/Categorias/Rutas/RutasIndividuales/actualizarCategorias.routes.js b/Categorias/Rutas/RutasIndividuales/actualizarCategorias.routes.js
new file mode 100644
index 00000000..67956f7d
--- /dev/null
+++ b/Categorias/Rutas/RutasIndividuales/actualizarCategorias.routes.js
@@ -0,0 +1,72 @@
+/**
+ * RF49 - Actualizar categoría de productos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF49
+ */
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/cat/ctrl/actualizarCategoria.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+
+/**
+ * @swagger
+ * /api/categorias/actualizar-categoria/{idCategoria}:
+ * put:
+ * summary: Actualiza una categoría y su lista de productos.
+ * description: Requiere autenticación y permisos adecuados. Valida que no se incluyan entradas maliciosas.
+ * tags:
+ * - Categorías
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * parameters:
+ * - in: path
+ * name: idCategoria
+ * required: true
+ * schema:
+ * type: integer
+ * description: ID de la categoría a actualizar
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * categoria:
+ * type: object
+ * properties:
+ * nombreCategoria:
+ * type: string
+ * descripcion:
+ * type: string
+ * productos:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * idProducto:
+ * type: integer
+ * responses:
+ * 200:
+ * description: Categoría actualizada correctamente.
+ * 400:
+ * description: Datos inválidos o entrada maliciosa detectada.
+ * 500:
+ * description: Error interno al actualizar la categoría.
+ */
+ruteador.put(
+ `${RUTAS.CATEGORIAS.ACTUALIZAR}/:idCategoria`,
+ validarYSanitizar,
+
+ revisarApiKey(),
+ autorizarToken,
+ verificarPermisos(PERMISOS.ACTUALIZAR_CATEGORIA_PRODUCTOS),
+ controlador.actualizarCategoria
+);
+
+module.exports = ruteador;
\ No newline at end of file
diff --git a/Categorias/Rutas/RutasIndividuales/consultarDetalleCategoria.routes.js b/Categorias/Rutas/RutasIndividuales/consultarDetalleCategoria.routes.js
new file mode 100644
index 00000000..0b755eaf
--- /dev/null
+++ b/Categorias/Rutas/RutasIndividuales/consultarDetalleCategoria.routes.js
@@ -0,0 +1,22 @@
+/**
+ * RF48 Leer categoría de productos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF48
+ */
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/cat/ctrl/consultarDetalleCategoria.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+ruteador.get(
+ `${RUTAS.CATEGORIAS.LEER}/:idCategoria`,
+ revisarApiKey(),
+ autorizarToken,
+ verificarPermisos(PERMISOS.LEER_CATEGORIA_PRODUCTOS),
+ controlador.consultarDetalleCategoria
+);
+
+module.exports = ruteador;
\ No newline at end of file
diff --git a/Categorias/Rutas/RutasIndividuales/consultarListaCategorias.routes.js b/Categorias/Rutas/RutasIndividuales/consultarListaCategorias.routes.js
new file mode 100644
index 00000000..e5b99c36
--- /dev/null
+++ b/Categorias/Rutas/RutasIndividuales/consultarListaCategorias.routes.js
@@ -0,0 +1,95 @@
+/**
+ * RF[47] Consulta lista de categorías - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF47
+ */
+
+/**
+ * @swagger
+ * /api/categorias/consultar-lista-categorias:
+ * post:
+ * summary: Consulta la lista de categorías de productos asociadas a un cliente.
+ * description: |
+ * Este endpoint permite consultar las categorías de productos disponibles para el
+ * cliente autenticado. El ID del cliente se obtiene automáticamente del token de autenticación.
+ * tags: [Categorías]
+ * security:
+ * - ApiKeyAuth: []
+ * requestBody:
+ * description: No requiere body. El ID del cliente se obtiene del token de autenticación.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties: {}
+ * responses:
+ * 200:
+ * description: Consulta exitosa. Se devuelve la lista de categorías.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Lista de categorías obtenida exitosamente."
+ * listaCategoria:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * idCategoria:
+ * type: integer
+ * example: 1
+ * nombreCategoria:
+ * type: string
+ * example: "Calzado"
+ * descripcion:
+ * type: string
+ * example: "Zapatos, botas y accesorios."
+ * cantidadProductos:
+ * type: integer
+ * example: 5
+ * idCliente:
+ * type: integer
+ * example: 123
+ * 204:
+ * description: No se encontraron categorías registradas para el cliente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "No se encontraron categorías registradas."
+ * 400:
+ * description: Error en el servidor al intentar obtener la lista de categorías.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Ocurrió un error al obtener la lista de categorías."
+ */
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/cat/ctrl/consultarListaCategorias.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+ruteador.post(
+ RUTAS.CATEGORIAS.CONSULTAR_LISTA_CATEGORIAS,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CONSULTAR_CATEGORIAS_PRODUCTOS),
+ controlador.consultarListaCategorias
+);
+
+module.exports = ruteador;
\ No newline at end of file
diff --git a/Categorias/Rutas/RutasIndividuales/crearCategoria.routes.js b/Categorias/Rutas/RutasIndividuales/crearCategoria.routes.js
new file mode 100644
index 00000000..1fb0cd91
--- /dev/null
+++ b/Categorias/Rutas/RutasIndividuales/crearCategoria.routes.js
@@ -0,0 +1,94 @@
+// RF[46] Crear categoria - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF46]
+
+const express = require('express');
+const ruteador = express.Router();
+const RUTAS = require('@altertex/util/const/rutas');
+const controlador = require('@altertex/cat/ctrl/crearCategoria.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const verificarPermiso = require('@altertex/util/inter/verificarPermisos');
+const PERMISOS = require('@altertex/util/const/permisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+/**
+ * @swagger
+ * /api/categorias/crear-categoria:
+ * post:
+ * summary: Crear una nueva categoría con productos asociados.
+ * description: Crea una categoría en la base de datos y asocia una lista de productos a ella. Requiere autenticación y permisos específicos.
+ * tags:
+ * - Categorías
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * categoria:
+ * type: object
+ * required:
+ * - nombreCategoria
+ * - productos
+ * properties:
+ * nombreCategoria:
+ * type: string
+ * example: "Nuevas Camisas"
+ * descripcion:
+ * type: string
+ * example: "Colección de camisas de temporada"
+ * productos:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * idProducto:
+ * type: integer
+ * example: 101
+ * responses:
+ * 201:
+ * description: Categoría creada exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * exito:
+ * type: string
+ * example: Categoría creada correctamente.
+ * 400:
+ * description: Datos inválidos proporcionados.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * error:
+ * type: string
+ * example: El nombre de la categoría o la lista de productos no son válidos.
+ * 500:
+ * description: Error interno al crear la categoría.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * error:
+ * type: string
+ * example: Error al crear la categoría.
+ */
+ruteador.post(
+ RUTAS.CATEGORIAS.CREAR_CATEGORIA,
+ validarYSanitizar,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermiso(PERMISOS.CREAR_CATEGORIA_PRODUCTOS),
+ controlador.crearCategoria
+);
+
+module.exports = ruteador;
diff --git a/Categorias/Rutas/RutasIndividuales/eliminarCategoria.routes.js b/Categorias/Rutas/RutasIndividuales/eliminarCategoria.routes.js
new file mode 100644
index 00000000..2afba0b2
--- /dev/null
+++ b/Categorias/Rutas/RutasIndividuales/eliminarCategoria.routes.js
@@ -0,0 +1,79 @@
+//RF[50] Elimina categoría de productos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF50]
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/cat/ctrl/eliminarCategoria.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/categorias/eliminar:
+ * post:
+ * summary: Eliminar categorías de productos.
+ * description: Elimina una o varias categorías de productos de la base de datos. Requiere autenticación y permisos específicos.
+ * tags:
+ * - Categorías
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * idsCategoria:
+ * type: array
+ * items:
+ * type: integer
+ * example: [1, 2, 3]
+ * responses:
+ * 200:
+ * description: Categorías eliminadas exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Categorías eliminadas correctamente.
+ * 404:
+ * description: Categorías no encontradas.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No se encontraron las categorías especificadas.
+ * 500:
+ * description: Error interno al eliminar las categorías.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error al eliminar las categorías.
+ */
+
+ruteador.post(
+ RUTAS.CATEGORIAS.ELIMINAR_CATEGORIA,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.ELIMINAR_CATEGORIA_PRODUCTOS),
+ controlador.eliminarCategoria
+);
+
+module.exports = ruteador;
diff --git a/Categorias/Rutas/indexCategorias.routes.js b/Categorias/Rutas/indexCategorias.routes.js
new file mode 100644
index 00000000..d412692f
--- /dev/null
+++ b/Categorias/Rutas/indexCategorias.routes.js
@@ -0,0 +1,17 @@
+const express = require('express');
+const ruteador = express.Router();
+const rutasConsultarListaCategorias = require('@altertex/cat/rutasInd/consultarListaCategorias.routes');
+const rutasCrearCategoria = require('@altertex/cat/rutasInd/crearCategoria.routes');
+const rutasEliminarCategoria = require('@altertex/cat/rutasInd/eliminarCategoria.routes');
+const rutasLeerCategoria = require('@altertex/cat/rutasInd/consultarDetalleCategoria.routes');
+const rutasActualizarCategoria = require('@altertex/cat/rutasInd/actualizarCategorias.routes');
+
+const RUTAS = require('@altertex/util/const/rutas');
+
+ruteador.use(RUTAS.CATEGORIAS.BASE, rutasConsultarListaCategorias);
+ruteador.use(RUTAS.CATEGORIAS.BASE, rutasCrearCategoria);
+ruteador.use(RUTAS.CATEGORIAS.BASE, rutasEliminarCategoria);
+ruteador.use(RUTAS.CATEGORIAS.BASE, rutasLeerCategoria);
+ruteador.use(RUTAS.CATEGORIAS.BASE, rutasActualizarCategoria);
+
+module.exports = ruteador;
diff --git a/Clientes/Controladores/actualizarClientes.controller.js b/Clientes/Controladores/actualizarClientes.controller.js
new file mode 100644
index 00000000..7abd24ae
--- /dev/null
+++ b/Clientes/Controladores/actualizarClientes.controller.js
@@ -0,0 +1,78 @@
+const MENSAJES = require('@altertex/util/const/mensajesClientes');
+const repositorio = require('@altertex/cli/repos/repositorioActualizarCliente');
+// RF14 - Actualiza Cliente - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF14
+
+/**
+ * Controlador para actualizar los datos de un cliente.
+ *
+ * Extrae los datos de actualización y la imagen (si existe) desde la petición.
+ * Valida que el ID del cliente esté presente y delega la actualización al repositorio.
+ * Devuelve una respuesta JSON con el estado correspondiente según el resultado.
+ *
+ * @param {Express.Request} req - Objeto de solicitud HTTP de Express.
+ * @param {object} req.body - Cuerpo de la solicitud con los datos del cliente.
+ * @param {string} req.body.idCliente - ID único del cliente a actualizar.
+ * @param {string} [req.body.nombreLegal] - Nuevo nombre legal del cliente (opcional).
+ * @param {string} [req.body.nombreComercial] - Nuevo nombre comercial del cliente (opcional).
+ * @param {object} [req.file] - Archivo de imagen cargado, si se proporciona.
+ * @param {Buffer} req.file.buffer - Contenido de la imagen en buffer.
+ * @param {string} req.file.mimetype - Tipo MIME del archivo de imagen.
+ *
+ * @param {Express.Response} res - Objeto de respuesta HTTP de Express.
+ *
+ * @returns {Promise} No retorna un valor directamente; envía la respuesta HTTP.
+ */
+exports.actualizarClientes = async (req, res) => {
+ const datosActualizacion = req.body;
+ const imagenActualizacion = req.file;
+
+ // Validación básica de la solicitud
+ if (!datosActualizacion.idCliente) {
+ return res
+ .status(MENSAJES.FORMATO_ID_CLIENTE_INVALIDO.codigo)
+ .json({ mensaje: MENSAJES.FORMATO_ID_CLIENTE_INVALIDO.mensaje });
+ }
+
+ // Validación de que al menos un dato para actualizar esté presente
+ if (
+ !datosActualizacion.nombreLegal
+ && !datosActualizacion.nombreComercial
+ && !imagenActualizacion
+ ) {
+ return res.status(MENSAJES.PARAMETROS_INVALIDOS.codigo).json({
+ mensaje:
+ 'Se debe proporcionar al menos un dato para actualizar (nombre legal, nombre comercial o imagen)',
+ });
+ }
+
+ try {
+ const mensaje = await repositorio.actualizarCliente(datosActualizacion, imagenActualizacion);
+
+ return res.status(MENSAJES.CLIENTE_ACTUALIZADO.codigo).json({ mensaje });
+ } catch (error) {
+ // Determinar el código de error adecuado basado en el mensaje de error
+ let codigoError = MENSAJES.ERROR_CLIENTE_ACTUALIZADO.codigo;
+ const mensajeError = error.message || MENSAJES.ERROR_CLIENTE_ACTUALIZADO.mensaje;
+
+ // Asignar códigos de error específicos según el tipo de error
+ if (error.message === MENSAJES.CLIENTE_NO_ENCONTRADO.mensaje) {
+ codigoError = MENSAJES.CLIENTE_NO_ENCONTRADO.codigo;
+ } else if (error.message === MENSAJES.CLIENTE_COMERCIAL_EXISTENTE.mensaje) {
+ codigoError = MENSAJES.CLIENTE_COMERCIAL_EXISTENTE.codigo;
+ } else if (error.message === MENSAJES.CLIENTE_FISCAL_EXISTENTE.mensaje) {
+ codigoError = MENSAJES.CLIENTE_FISCAL_EXISTENTE.codigo;
+ } else if (error.message.includes('No se encontró la imagen')) {
+ codigoError = 404;
+ } else if (error.message.includes('Error al actualizar la imagen')) {
+ codigoError = 500;
+ } else if (error.message.includes('Error al actualizar los datos')) {
+ codigoError = 500;
+ } else if (error.message.includes('No se pudo actualizar')) {
+ codigoError = 400;
+ }
+
+ console.error(`[ERROR] ActualizarClientes: ${error.message}`);
+
+ return res.status(codigoError).json({ mensaje: mensajeError });
+ }
+};
diff --git a/Clientes/Controladores/consultarClientes.controller.js b/Clientes/Controladores/consultarClientes.controller.js
new file mode 100644
index 00000000..44c2b512
--- /dev/null
+++ b/Clientes/Controladores/consultarClientes.controller.js
@@ -0,0 +1,79 @@
+const repositorio = require('@altertex/cli/repos/repositorioObtenerLista');
+const obtenerImagenFolder = require('@altertex/util/ser/obtenerImagenFolder');
+const MENSAJES_CLIENTES = require('@altertex/util/const/mensajesClientes');
+
+/**
+ * Controlador para consultar el sistema de un cliente específico.
+ *
+ * RF12 - Consulta Lista de Clientes - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF12
+ *
+ * @async
+ * @function consultarSistema
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.user - Información del usuario autenticado (inyectada por middleware).
+ * @param {string} req.user.correo - Correo electrónico del usuario autenticado.
+ * @param {Array} req.user.permisos - Permisos del usuario.
+ * @param {Array} req.user.clientesAsociados - Lista de IDs de clientes a los que el usuario tiene acceso.
+ * @param {object} req.body - Cuerpo de la solicitud.
+ * @param {string|number} req.body.idCliente - ID del cliente que se desea consultar.
+ * @param {object} res - Objeto de respuesta de Express.
+ *
+ * @returns {Response} Respuesta HTTP con estado:
+ * - 200 si la consulta es exitosa y se emite un nuevo token con el cliente seleccionado.
+ * - 400 si el formato del ID del cliente no es válido.
+ * - 403 si el usuario no está autorizado para consultar ese cliente.
+ * - 404 si el cliente no tiene sistema asociado.
+ * - 500 si ocurre un error en el servidor al consultar el sistema.
+ *
+ * @throws {Error} Si ocurre un error inesperado durante la operación.
+ */
+exports.consultarLista = async (req, res) => {
+ let clientesAsociados = req.user.clientesAsociados;
+
+ if (!Array.isArray(clientesAsociados)) {
+ return res.status(MENSAJES_CLIENTES.CLIENTES_ASOCIADOS_NO_PROPORCIONADOS.codigo).json({
+ mensaje: MENSAJES_CLIENTES.CLIENTES_ASOCIADOS_NO_PROPORCIONADOS.mensaje,
+ });
+ }
+
+ clientesAsociados = clientesAsociados.map((id) => parseInt(id)).filter((id) => !isNaN(id));
+
+ if (clientesAsociados.length === 0) {
+ return res
+ .status(MENSAJES_CLIENTES.LISTA_CLIENTES_INVALIDA.codigo)
+ .json({ mensaje: MENSAJES_CLIENTES.LISTA_CLIENTES_INVALIDA.mensaje });
+ }
+
+ try {
+ const listaClientes = await repositorio.obtenerLista(clientesAsociados);
+ req.clientes = listaClientes;
+
+ if (!Array.isArray(listaClientes) || listaClientes.length === 0) {
+ return res
+ .status(MENSAJES_CLIENTES.LISTA_CLIENTES_VACIA.codigo)
+ .json({ mensaje: MENSAJES_CLIENTES.LISTA_CLIENTES_VACIA.mensaje });
+ }
+
+ const folder = 'clientes/';
+
+ let listaClientesConImagen;
+ try {
+ listaClientesConImagen = await obtenerImagenFolder(req, folder);
+ } catch {
+ listaClientesConImagen = listaClientes.map((cliente) => ({
+ ...cliente,
+ urlImagen: '/placeholder.png',
+ }));
+ }
+
+ return res.status(MENSAJES_CLIENTES.CONSULTA_LISTA_EXITOSA.codigo).json({
+ mensaje: MENSAJES_CLIENTES.CONSULTA_LISTA_EXITOSA.mensaje,
+ clientes: listaClientesConImagen,
+ });
+ } catch (error) {
+ return res.status(MENSAJES_CLIENTES.ERROR_CONSULTAR_LISTA_CLIENTES.codigo).json({
+ mensaje: MENSAJES_CLIENTES.ERROR_CONSULTAR_LISTA_CLIENTES.mensaje,
+ error: error.message,
+ });
+ }
+};
diff --git a/Clientes/Controladores/consultarSistema.controller.js b/Clientes/Controladores/consultarSistema.controller.js
new file mode 100644
index 00000000..03209dfa
--- /dev/null
+++ b/Clientes/Controladores/consultarSistema.controller.js
@@ -0,0 +1,89 @@
+const jwt = require('jsonwebtoken');
+const repositorio = require('@altertex/cli/repos/repositorioObtenerCliente');
+const MENSAJES_CLIENTES = require('@altertex/util/const/mensajesClientes');
+
+/**
+ * Controlador para consultar el sistema de un cliente específico.
+ *
+ *
+ * @async
+ * @function consultarSistema
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.user - Información del usuario autenticado (inyectada por middleware).
+ * @param {string} req.user.correo - Correo electrónico del usuario autenticado.
+ * @param {Array} req.user.permisos - Permisos del usuario.
+ * @param {Array} req.user.clientesAsociados - Lista de IDs de clientes a los que el usuario tiene acceso.
+ * @param {string} req.user.nombreCompleto - Nombre completo del usuario autenticado.
+ * @param {object} req.body - Cuerpo de la solicitud.
+ * @param {string|number} req.body.idCliente - ID del cliente que se desea consultar.
+ *
+ * @param {object} res - Objeto de respuesta de Express.
+ *
+ * @returns {Response} Respuesta HTTP con estado:
+ * - 200 si la consulta es exitosa y se emite un nuevo token con el cliente seleccionado.
+ * - 400 si el formato del ID del cliente no es válido (idCliente no es un número).
+ * - 403 si el usuario no está autorizado para consultar ese cliente (no tiene acceso al cliente).
+ * - 404 si el cliente no tiene sistema asociado (no se encuentra en la base de datos).
+ * - 500 si ocurre un error en el servidor al consultar el sistema.
+ *
+ * @throws {Error} Si ocurre un error inesperado durante la operación.
+ */
+exports.consultarSistema = async (req, res) => {
+ const idCliente = req.body.idCliente;
+ const { correo, permisos, clientesAsociados, nombreCompleto } = req.user;
+
+ const tiempoExpiracion = 8 * 60 * 60 * 1000;
+
+ // if (isNaN(idCliente)) {
+ // return res
+ // .status(MENSAJES_CLIENTES.FORMATO_ID_CLIENTE_INVALIDO.codigo)
+ // .json({ mensaje: MENSAJES_CLIENTES.FORMATO_ID_CLIENTE_INVALIDO.mensaje });
+ // }
+
+ if (!clientesAsociados.includes(idCliente)) {
+ return res
+ .status(MENSAJES_CLIENTES.ACCESO_NO_AUTORIZADO.codigo)
+ .json({ mensaje: MENSAJES_CLIENTES.ACCESO_NO_AUTORIZADO.mensaje });
+ }
+
+ try {
+ const sistema = await repositorio.obtenerCliente(idCliente);
+ if (!sistema) {
+ return res
+ .status(MENSAJES_CLIENTES.CLIENTE_SIN_SISTEMA.codigo)
+ .json({ mensaje: MENSAJES_CLIENTES.CLIENTE_SIN_SISTEMA.mensaje });
+ }
+
+ const nuevoToken = jwt.sign(
+ {
+ correo,
+ permisos,
+ clientesAsociados,
+ clienteSeleccionado: idCliente,
+ },
+ process.env.JWT_SECRET,
+ { expiresIn: '8h' }
+ );
+
+ res.cookie('token', nuevoToken, {
+ httpOnly: true,
+ secure: true,
+ sameSite: 'None',
+ });
+
+ res.cookie('nombreUsuario', nombreCompleto, {
+ httpOnly: false,
+ secure: true,
+ sameSite: 'None',
+ maxAge: tiempoExpiracion,
+ });
+
+ return res.status(MENSAJES_CLIENTES.CONSULTA_EXITOSA.codigo).json({
+ mensaje: MENSAJES_CLIENTES.CONSULTA_EXITOSA.mensaje,
+ });
+ } catch {
+ return res
+ .status(MENSAJES_CLIENTES.ERROR_CONSULTAR_SISTEMA.codigo)
+ .json({ mensaje: MENSAJES_CLIENTES.ERROR_CONSULTAR_SISTEMA.mensaje });
+ }
+};
diff --git a/Clientes/Controladores/crearCliente.controller.js b/Clientes/Controladores/crearCliente.controller.js
new file mode 100644
index 00000000..ac929fe1
--- /dev/null
+++ b/Clientes/Controladores/crearCliente.controller.js
@@ -0,0 +1,91 @@
+const repositorio = require('@altertex/cli/repos/repositorioCrearCliente');
+const MENSAJES = require('@altertex/util/const/mensajesClientes');
+const subirImagen = require('@altertex/util/ser/subirImagen');
+
+/**
+ * Controlador para crear un nuevo cliente.
+ *
+ * Este controlador realiza las siguientes validaciones y operaciones:
+ * - Verifica que el nombre comercial del cliente sea válido.
+ * - Verifica que el nombre fiscal del cliente sea válido.
+ * - Verifica que la imagen del cliente sea válida.
+ * - Valida que el nombre comercial del cliente no esté duplicado en la base de datos.
+ * - Valida que el nombre fiscal del cliente no esté duplicado en la base de datos.
+ * - Inserta el cliente si todas las validaciones son exitosas.
+ *
+ * @async
+ * @function crearRol
+ * @param {Express.Request} req - Objeto de solicitud HTTP. Se espera que el cuerpo (`req.body`) contenga:
+ * @param {string} req.body.cliente.nombreComercial - Nombre comercial del cliente.
+ * @param {string} req.body.cliente.nombreFiscal - Nombre fiscal del cliente.
+ * @param {number[]} req.body.cliente.imagen - Imagen del cliente.
+ * @param {Express.Response} res - Objeto de respuesta HTTP.
+ * @returns {Promise} - Respuesta JSON con el estado de la creación del rol.
+ */
+exports.crearCliente = async (req, res) => {
+ const { nombreComercial, nombreFiscal } = req.body;
+ const imagen = req.file;
+
+ // Validación del nombre comercial del cliente
+ if (!nombreComercial || typeof nombreComercial !== 'string') {
+ return res.status(400).json({ mensaje: MENSAJES.CAMPO_OBLIGATORIO.mensaje });
+ }
+
+ // Validación del nombre fiscal del cliente
+ if (!nombreFiscal || typeof nombreFiscal !== 'string') {
+ return res.status(400).json({ mensaje: MENSAJES.CAMPO_OBLIGATORIO.mensaje });
+ }
+
+ if (!imagen) {
+ return res.status(400).json({ mensaje: MENSAJES.CAMPO_OBLIGATORIO.mensaje });
+ }
+
+ try {
+ // Verificar si ya existe un cliente con ese nombre comercial
+ const existeComercial = await repositorio.verificarNombreComercial(nombreComercial);
+ if (existeComercial) {
+ return res.status(400).json({ mensaje: MENSAJES.CLIENTE_COMERCIAL_EXISTENTE.mensaje });
+ }
+
+ // Verificar si ya existe un cliente con ese nombre comercial
+ const existeFiscal = await repositorio.verificarNombreFiscal(nombreFiscal);
+ if (existeFiscal) {
+ return res.status(400).json({ mensaje: MENSAJES.CLIENTE_FISCAL_EXISTENTE.mensaje });
+ }
+
+ // Crear el cliente
+ const resultadoCliente = await repositorio.crearCliente(nombreComercial, nombreFiscal);
+ const resultadoVincular = await repositorio.vincularUsuarioCliente(resultadoCliente.insertId);
+
+ if (imagen) {
+ const nombreImagen = await subirImagen(imagen, 'clientes', nombreComercial);
+
+ const resultadoImagen = await repositorio.crearImagenCliente(
+ nombreComercial,
+ nombreImagen.split('/')[1]
+ );
+
+ const resultado = await repositorio.vincularImagenCliente(
+ resultadoImagen.insertId,
+ resultadoCliente.insertId
+ );
+ if (
+ resultadoCliente.insertId
+ && resultadoVincular.affectedRows
+ && resultadoImagen.insertId
+ && resultado.affectedRows === 1
+ ) {
+ return res.status(201).json({ mensaje: MENSAJES.CLIENTE_CREADO.mensaje });
+ }
+ } else {
+ // ✅ manejar caso sin imagen
+ if (resultadoCliente.insertId && resultadoVincular.affectedRows === 1) {
+ return res.status(201).json({ mensaje: MENSAJES.CLIENTE_CREADO.mensaje });
+ } else {
+ return res.status(500).json({ mensaje: MENSAJES.ERROR_CREACION.mensaje });
+ }
+ }
+ } catch {
+ return res.status(500).json({ mensaje: MENSAJES.ERROR_CREACION.mensaje });
+ }
+};
diff --git a/Clientes/Controladores/eliminarCliente.controller.js b/Clientes/Controladores/eliminarCliente.controller.js
new file mode 100644
index 00000000..a4098669
--- /dev/null
+++ b/Clientes/Controladores/eliminarCliente.controller.js
@@ -0,0 +1,61 @@
+// Importaciones necesarias
+const repositorio = require('@altertex/cli/repos/repositorioEliminarCliente');
+const MENSAJES_CLIENTES = require('@altertex/util/const/mensajesClientes');
+const extraerNombreArchivoS3 = require('@altertex/util/ser/extraerNombreArchivoS3');
+const eliminarImagenS3 = require('@altertex/util/ser/eliminarImagenS3');
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_CLIENTES = require('@altertex/util/const/consultasClientes');
+
+/**
+ * Controlador para eliminar un cliente de la base de datos y su imagen de S3.
+ * @see [RF15 - Elimina Cliente](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF15)
+ *
+ * @async
+ * @function eliminarCliente
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.body - Cuerpo de la solicitud HTTP.
+ * @param {number} req.body.idCliente - ID del cliente a eliminar.
+ * @param {object} res - Objeto de respuesta de Express.
+ * @returns {Promise} Respuesta HTTP con estado.
+ * @throws {Error} Si ocurre un error durante la eliminación.
+ */
+exports.eliminarCliente = async (req, res) => {
+ try {
+ const idCliente = parseInt(req.body.idCliente);
+
+ if (isNaN(idCliente)) {
+ return res
+ .status(MENSAJES_CLIENTES.CLIENTE_INVALIDO.codigo)
+ .json({ mensaje: MENSAJES_CLIENTES.CLIENTE_INVALIDO.mensaje });
+ }
+
+ // Obtener nombre de la imagen asociada (si existe)
+ let nombreImagen = '';
+ const resultadoImagen = await correrQuery(CONSULTAS_CLIENTES.OBTENER_NOMBRE_IMAGEN, [idCliente]);
+ if (resultadoImagen.length > 0 && resultadoImagen[0].urlImagen) {
+ nombreImagen = extraerNombreArchivoS3(resultadoImagen[0].urlImagen);
+ }
+
+ // Eliminar cliente
+ const resultado = await repositorio.eliminarClientePorId(idCliente);
+
+ if (resultado.affectedRows === 0) {
+ return res
+ .status(MENSAJES_CLIENTES.CLIENTE_NO_ENCONTRADO.codigo)
+ .json({ mensaje: MENSAJES_CLIENTES.CLIENTE_NO_ENCONTRADO.mensaje });
+ }
+
+ // Eliminar imagen si hay nombre válido
+ if (nombreImagen) {
+ await eliminarImagenS3('clientes/', nombreImagen);
+ }
+
+ return res
+ .status(MENSAJES_CLIENTES.CLIENTE_ELIMINADO.codigo)
+ .json({ mensaje: MENSAJES_CLIENTES.CLIENTE_ELIMINADO.mensaje });
+ } catch {
+ return res
+ .status(MENSAJES_CLIENTES.ERROR_ELIMINAR_CLIENTE.codigo)
+ .json({ mensaje: MENSAJES_CLIENTES.ERROR_ELIMINAR_CLIENTE.mensaje });
+ }
+};
\ No newline at end of file
diff --git a/Clientes/Controladores/leerCliente.controller.js b/Clientes/Controladores/leerCliente.controller.js
new file mode 100644
index 00000000..3a7ded03
--- /dev/null
+++ b/Clientes/Controladores/leerCliente.controller.js
@@ -0,0 +1,53 @@
+const repositorio = require('@altertex/cli/repos/repositorioLeerCliente');
+const obtenerImagenCliente = require('@altertex/util/ser/obtenerImagenCliente');
+const MENSAJES_CLIENTES = require('@altertex/util/const/mensajesClientes');
+
+/**
+ * Lee los detalles de un cliente desde la base de datos utilizando su ID.
+ *
+ * Valida el parámetro `idCliente` y obtiene la información del cliente a través del repositorio.
+ * Si el cliente no es encontrado o el parámetro es inválido, retorna un error.
+ *
+ * @param {Express.Request} req - La solicitud HTTP que contiene el `idCliente` en el cuerpo.
+ * @param {Express.Response} res - La respuesta HTTP para enviar el resultado al cliente.
+ * @returns {Promise} Responde con el cliente encontrado o un mensaje de error.
+ *
+ * @see RF13 Leer cliente](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/rf13/)
+ */
+exports.leerCliente = async (req, res) => {
+ const idCliente = parseInt(req.body.idCliente);
+
+ if (isNaN(idCliente)) {
+ return res
+ .status(MENSAJES_CLIENTES.PARAMETROS_INVALIDOS.codigo)
+ .json({ mensaje: MENSAJES_CLIENTES.PARAMETROS_INVALIDOS.mensaje });
+ }
+
+ try {
+ const cliente = await repositorio.obtenerClientePorId(idCliente);
+
+ if (!cliente) {
+ return res
+ .status(MENSAJES_CLIENTES.CLIENTE_NO_ENCONTRADO.codigo)
+ .json({ mensaje: MENSAJES_CLIENTES.CLIENTE_NO_ENCONTRADO.mensaje });
+ }
+ let imagenCliente;
+ try {
+ imagenCliente = await obtenerImagenCliente(cliente.urlImagen);
+ } catch {
+ imagenCliente = '/placeholder.png'; // URL genérica de placeholder
+ }
+
+ return res.status(MENSAJES_CLIENTES.CONSULTA_EXITOSA.codigo).json({
+ mensaje: MENSAJES_CLIENTES.CONSULTA_EXITOSA.mensaje,
+ cliente: {
+ ...cliente,
+ imagenCliente,
+ },
+ });
+ } catch {
+ return res
+ .status(MENSAJES_CLIENTES.ERROR_CONSULTAR_CLIENTE.codigo)
+ .json({ mensaje: MENSAJES_CLIENTES.ERROR_CONSULTAR_CLIENTE.mensaje });
+ }
+};
\ No newline at end of file
diff --git a/Clientes/Datos/Repositorios/repositorioActualizarCliente.js b/Clientes/Datos/Repositorios/repositorioActualizarCliente.js
new file mode 100644
index 00000000..a18817f1
--- /dev/null
+++ b/Clientes/Datos/Repositorios/repositorioActualizarCliente.js
@@ -0,0 +1,109 @@
+const MENSAJES = require('@altertex/util/const/mensajesClientes');
+const CONSULTAS = require('@altertex/util/const/consultasClientes');
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const enviarS3 = require('@altertex/util/ser/enviarS3');
+// RF14 - Actualiza Cliente - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF14
+
+/**
+ * Actualiza los datos de un cliente, incluyendo su nombre legal y/o comercial,
+ * y la imagen asociada al cliente si se proporciona.
+ *
+ * @param {object} datosActualizacion - Datos de actualización del cliente.
+ * @param {string} datosActualizacion.idCliente - ID único del cliente a actualizar.
+ * @param {string} [datosActualizacion.nombreLegal] - Nuevo nombre legal del cliente (opcional).
+ * @param {string} [datosActualizacion.nombreComercial] - Nuevo nombre comercial del cliente (opcional).
+ * @param {object} [imagenActualizacion] - Información de la imagen a actualizar.
+ * @param {Buffer} imagenActualizacion.buffer - El buffer de la imagen a cargar.
+ * @param {string} imagenActualizacion.mimetype - Tipo MIME de la imagen (ej. 'image/jpeg').
+ *
+ * @returns {string} Mensaje indicando si la actualización fue exitosa.
+ *
+ * @throws {Error} Lanza un error si ocurre un problema durante la actualización del cliente.
+ */
+exports.actualizarCliente = async (datosActualizacion, imagenActualizacion) => {
+ const { idCliente, nombreLegal, nombreComercial } = datosActualizacion;
+
+ const resultadoCliente = await correrQuery(CONSULTAS.OBTENER_CLIENTE, [idCliente]);
+ if (!resultadoCliente || resultadoCliente.length === 0) {
+ throw new Error(MENSAJES.CLIENTE_NO_ENCONTRADO.mensaje);
+ }
+
+ if (nombreComercial) {
+ const [resultadoNombreComercial] = await correrQuery(CONSULTAS.VERIFICAR_NOMBRE_COMERCIAL, [
+ nombreComercial,
+ ]);
+ const existeNombreComercial = Object.values(resultadoNombreComercial)[0];
+
+ if (existeNombreComercial === 1) {
+ const [clienteActual] = await correrQuery(CONSULTAS.OBTENER_CLIENTE, [idCliente]);
+ if (clienteActual && clienteActual.nombreComercial !== nombreComercial) {
+ throw new Error(MENSAJES.CLIENTE_COMERCIAL_EXISTENTE.mensaje);
+ }
+ }
+ }
+
+ if (nombreLegal) {
+ const [resultadoNombreFiscal] = await correrQuery(CONSULTAS.VERIFICAR_NOMBRE_FISCAL, [
+ nombreLegal,
+ ]);
+ const existeNombreFiscal = Object.values(resultadoNombreFiscal)[0];
+
+ if (existeNombreFiscal === 1) {
+ const [clienteActual] = await correrQuery(CONSULTAS.OBTENER_CLIENTE, [idCliente]);
+ if (clienteActual && clienteActual.nombreFiscal !== nombreLegal) {
+ throw new Error(MENSAJES.CLIENTE_FISCAL_EXISTENTE.mensaje);
+ }
+ }
+ }
+
+ if (imagenActualizacion) {
+ const resultadoImagen = await correrQuery(CONSULTAS.OBTENER_NOMBRE_IMAGEN, [idCliente]);
+ if (!resultadoImagen || resultadoImagen.length === 0 || !resultadoImagen[0].urlImagen) {
+ throw new Error('No se encontró la imagen del cliente para actualizar');
+ }
+
+ const nombreImagen = resultadoImagen[0];
+ const parametros = {
+ Bucket: process.env.AWS_BUCKET_NAME,
+ Key: `clientes/${nombreImagen.urlImagen}`,
+ Body: imagenActualizacion.buffer,
+ ContentType: imagenActualizacion.mimetype,
+ };
+
+ await enviarS3(parametros);
+ }
+
+ if (!nombreLegal && !nombreComercial) {
+ return MENSAJES.CLIENTE_ACTUALIZADO.mensaje;
+ }
+
+ let resultadoQuery;
+ if (nombreLegal && nombreComercial) {
+ resultadoQuery = await correrQuery(CONSULTAS.ACTUALIZAR_AMBOS_NOMBRES, [
+ nombreComercial,
+ nombreLegal,
+ idCliente,
+ ]);
+ if (!resultadoQuery || resultadoQuery.affectedRows === 0) {
+ throw new Error('No se pudo actualizar los nombres del cliente');
+ }
+ } else if (nombreLegal) {
+ resultadoQuery = await correrQuery(CONSULTAS.ACTUALIZAR_NOMBRE_FISCAL, [
+ nombreLegal,
+ idCliente,
+ ]);
+ if (!resultadoQuery || resultadoQuery.affectedRows === 0) {
+ throw new Error('No se pudo actualizar el nombre fiscal del cliente');
+ }
+ } else if (nombreComercial) {
+ resultadoQuery = await correrQuery(CONSULTAS.ACTUALIZAR_NOMBRE_COMERCIAL, [
+ nombreComercial,
+ idCliente,
+ ]);
+ if (!resultadoQuery || resultadoQuery.affectedRows === 0) {
+ throw new Error('No se pudo actualizar el nombre comercial del cliente');
+ }
+ }
+
+ return MENSAJES.CLIENTE_ACTUALIZADO.mensaje;
+};
diff --git a/Clientes/Datos/Repositorios/repositorioCrearCliente.js b/Clientes/Datos/Repositorios/repositorioCrearCliente.js
new file mode 100644
index 00000000..9c3ce440
--- /dev/null
+++ b/Clientes/Datos/Repositorios/repositorioCrearCliente.js
@@ -0,0 +1,111 @@
+const QUERY = require('@altertex/util/const/consultasClientes');
+const correrQuery = require('@altertex/util/ser/correrQuery');
+
+/**
+ * Verifica si un cliente con el nombre comercial especificado ya existe en la base de datos.
+ *
+ * @async
+ * @function verificarNombreComercial
+ * @param {string} nombre - Nombre comercial del cliente a verificar.
+ * @returns {Promise} Retorna `true` si existe otro cliente con ese nombre comercial, `false` en caso contrario.
+ */
+exports.verificarNombreComercial = async (nombre) => {
+ const resultado = await correrQuery(QUERY.VERIFICAR_NOMBRE_COMERCIAL, [nombre]);
+ const valor = Object.values(resultado[0])[0];
+ return valor == 1;
+};
+
+/**
+ * Verifica si un cliente con el nombre fiscal especificado ya existe en la base de datos.
+ *
+ * @async
+ * @function verificarNombreFiscal
+ * @param {string} nombre - Nombre fiscal del cliente a verificar.
+ * @returns {Promise} Retorna `true` si existe otro cliente con ese nombre fiscal, `false` en caso contrario.
+ */
+exports.verificarNombreFiscal = async (nombre) => {
+ const resultado = await correrQuery(QUERY.VERIFICAR_NOMBRE_FISCAL, [nombre]);
+ const valor = Object.values(resultado[0])[0];
+ return valor == 1;
+};
+
+/**
+ * Crea un nuevo cliente en la base de datos.
+ *
+ * @async
+ * @function crearCliente
+ * @param {string} nombreComercial - Nombre comercial del nuevo cliente.
+ * @param {string} nombreFiscal - Nombre fiscal del nuevo cliente.
+ * @returns {Promise} Retorna el resultado de la operación de inserción, incluyendo el ID del nuevo cliente.
+ */
+exports.crearCliente = async (nombreComercial, nombreFiscal) => {
+ try {
+ const resultadoCliente = await correrQuery(QUERY.CREAR_CLIENTE, [
+ nombreComercial,
+ nombreFiscal,
+ ]);
+ return resultadoCliente;
+ } catch (error) {
+ console.error('Error al crear cliente:', error);
+ throw new Error('Error al crear cliente');
+ }
+};
+
+/**
+ * Vincula el usuario autenticado al cliente recién creado.
+ *
+ * @async
+ * @function vincularUsuarioCliente
+ * @param {number} idCliente - ID del cliente con el que se debe vincular el usuario.
+ * @returns {Promise} Resultado de la operación de vinculación.
+ */
+exports.vincularUsuarioCliente = async (idCliente) => {
+ try {
+ const resultadoVincular = await correrQuery(QUERY.VINCULAR_USUARIO_CLIENTE, [idCliente]);
+ return resultadoVincular;
+ } catch (error) {
+ console.error('Error al vincular usuario al cliente:', error);
+ throw new Error('Error al vincular usuario al cliente');
+ }
+};
+
+/**
+ * Inserta una imagen asociada a un cliente en la base de datos.
+ *
+ * @async
+ * @function crearImagenCliente
+ * @param {string} nombreComercial - Nombre comercial del cliente para asociar en la descripción.
+ * @param {string} imagen - Ruta o identificador de la imagen a registrar.
+ * @returns {Promise} Resultado de la operación de inserción de imagen.
+ */
+exports.crearImagenCliente = async (nombreComercial, imagen) => {
+ try {
+ const resultadoImagen = await correrQuery(QUERY.CREAR_IMAGEN_CLIENTE, [
+ imagen,
+ `Logo de ${nombreComercial}`,
+ ]);
+ return resultadoImagen;
+ } catch (error) {
+ console.error('Error al crear imagen del cliente:', error);
+ throw new Error('Error al crear imagen del cliente');
+ }
+};
+
+/**
+ * Vincula una imagen previamente registrada con un cliente específico.
+ *
+ * @async
+ * @function vincularImagenCliente
+ * @param {number} imagenId - ID de la imagen a vincular.
+ * @param {number} clienteId - ID del cliente con el que se vinculará la imagen.
+ * @returns {Promise} Resultado de la operación de vinculación.
+ */
+exports.vincularImagenCliente = async (imagenId, clienteId) => {
+ try {
+ const resultado = await correrQuery(QUERY.VINCULAR_IMAGEN_CLIENTE, [imagenId, clienteId]);
+ return resultado;
+ } catch (error) {
+ console.error('Error al vincular imagen y cliente', error);
+ throw new Error('Error al vincular imagen y cliente');
+ }
+};
diff --git a/Clientes/Datos/Repositorios/repositorioEliminarCliente.js b/Clientes/Datos/Repositorios/repositorioEliminarCliente.js
new file mode 100644
index 00000000..2d7c46b6
--- /dev/null
+++ b/Clientes/Datos/Repositorios/repositorioEliminarCliente.js
@@ -0,0 +1,22 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_CLIENTES = require('@altertex/util/const/consultasClientes');
+
+/**
+ * Elimina un cliente de la base de datos.
+ *
+ * @async
+ * @function eliminarClientePorId
+ * @param {number} idCliente - ID del cliente a eliminar.
+ * @returns {Promise<{affectedRows: number}>} Resultado de la operación con número de filas afectadas.
+ * @throws {Error} Si ocurre un error durante la eliminación.
+ * @see [RF15 - Elimina Cliente](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF15)
+ */
+exports.eliminarClientePorId = async (idCliente) => {
+ const query = CONSULTAS_CLIENTES.ELIMINAR_CLIENTE;
+ try {
+ const resultado = await correrQuery(query, [idCliente]);
+ return resultado;
+ } catch {
+ throw new Error('Ocurrio un error eliminando al cliente.');
+ }
+};
\ No newline at end of file
diff --git a/Clientes/Datos/Repositorios/repositorioLeerCliente.js b/Clientes/Datos/Repositorios/repositorioLeerCliente.js
new file mode 100644
index 00000000..6cacf62e
--- /dev/null
+++ b/Clientes/Datos/Repositorios/repositorioLeerCliente.js
@@ -0,0 +1,37 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_CLIENTES = require('@altertex/util/const/consultasClientes');
+
+/**
+ * Obtiene un cliente desde la base de datos mediante su ID.
+ *
+ * Ejecuta una consulta SQL y retorna el primer cliente encontrado o `null` si no existe.
+ *
+ * @param {number|string} idCliente - ID del cliente a buscar.
+ * @returns {Promise} El cliente encontrado o `null` si no existe.
+ * @throws {Error} Si ocurre un error al ejecutar la consulta.
+ *
+ * @see [RF13 Leer cliente](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/rf13/)
+ */
+exports.obtenerClientePorId = async (idCliente) => {
+ const query = CONSULTAS_CLIENTES.LEER_CLIENTE;
+
+ try {
+ const resultado = await correrQuery(query, [idCliente]);
+
+ if (resultado.length === 0) return null;
+
+ const cliente = {
+ idCliente: resultado[0].idCliente,
+ nombreLegal: resultado[0].nombreFiscal,
+ nombreVisible: resultado[0].nombreComercial,
+ empleados: resultado[0].empleados,
+ usuariosAsignados: resultado[0].usuariosAsignados,
+ numeroEmpleados: resultado[0].numeroEmpleados,
+ urlImagen: resultado[0].urlImagen,
+ };
+
+ return cliente;
+ } catch {
+ throw new Error('Ocurrio un error obteniendo el cliente.');
+ }
+};
\ No newline at end of file
diff --git a/Clientes/Datos/Repositorios/repositorioObtenerCliente.js b/Clientes/Datos/Repositorios/repositorioObtenerCliente.js
new file mode 100644
index 00000000..abfbeb24
--- /dev/null
+++ b/Clientes/Datos/Repositorios/repositorioObtenerCliente.js
@@ -0,0 +1,29 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_CLIENTES = require('@altertex/util/const/consultasClientes');
+
+/**
+ * Obtiene la información de un cliente a partir de su ID.
+ *
+ * RF12 - Consulta Lista de Clientes - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF12
+ *
+ * @async
+ * @function obtenerCliente
+ * @param {number} idCliente - ID del cliente a buscar.
+ *
+ * @returns {Promise} Objeto con la información del cliente si se encuentra,
+ * o un string con un mensaje de error si ocurre un fallo durante la operación.
+ */
+exports.obtenerCliente = async (idCliente) => {
+ try {
+ const query = CONSULTAS_CLIENTES.OBTENER_CLIENTE;
+ const resultado = await correrQuery(query, [idCliente]);
+
+ if (!resultado || resultado.length === 0) {
+ return `No se encontró un cliente con el ID ${idCliente}`;
+ }
+
+ return resultado[0];
+ } catch (error) {
+ return `Error obteniendo cliente: ${error}`;
+ }
+};
diff --git a/Clientes/Datos/Repositorios/repositorioObtenerLista.js b/Clientes/Datos/Repositorios/repositorioObtenerLista.js
new file mode 100644
index 00000000..92b664a3
--- /dev/null
+++ b/Clientes/Datos/Repositorios/repositorioObtenerLista.js
@@ -0,0 +1,23 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_CLIENTES = require('@altertex/util/const/consultasClientes');
+
+/**
+ * Obtiene la lista de clientes asociados según los IDs proporcionados.
+ *
+ * @async
+ * @function obtenerLista
+ * @param {number[]} clientesAsociados - Arreglo de IDs de clientes asociados al usuario.
+ * @returns {Promise} Arreglo con la información de los clientes,
+ * o un string con un mensaje de error si ocurre un fallo durante la operación.
+ */
+exports.obtenerLista = async (clientesAsociados) => {
+ try {
+ const query = CONSULTAS_CLIENTES.OBTENER_LISTA;
+
+ const resultado = await correrQuery(query, [clientesAsociados]);
+
+ return resultado;
+ } catch (error) {
+ return `Error obteniendo lista de clientes: ${error}`;
+ }
+};
diff --git a/Clientes/Rutas/RutasIndividuales/actualizarClientes.routes.js b/Clientes/Rutas/RutasIndividuales/actualizarClientes.routes.js
new file mode 100644
index 00000000..2cfd3f66
--- /dev/null
+++ b/Clientes/Rutas/RutasIndividuales/actualizarClientes.routes.js
@@ -0,0 +1,102 @@
+const express = require('express');
+const ruteador = express.Router();
+const multer = require('multer');
+const RUTAS = require('@altertex/util/const/rutas');
+const PERMISOS = require('@altertex/util/const/permisos');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const controlador = require('@altertex/cli/ctrl/actualizarClientes.controller');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+const storage = multer.memoryStorage();
+const upload = multer({ storage });
+
+// RF14 - Actualiza Cliente - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF14
+/**
+ * @swagger
+ * /api/clientes/actualizar-cliente:
+ * put:
+ * tags:
+ * - Clientes
+ * summary: Actualiza los datos de un cliente
+ * description: >
+ * Esta ruta permite actualizar los datos de un cliente, incluyendo su nombre legal, nombre comercial y una imagen opcional.
+ * Requiere autenticación mediante token JWT, una API key válida, y permisos específicos (ACTUALIZAR_CLIENTE).
+ * operationId: actualizarCliente
+ * security:
+ * - ApiKeyAuth: []
+ * - bearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * multipart/form-data:
+ * schema:
+ * type: object
+ * required:
+ * - idCliente
+ * properties:
+ * idCliente:
+ * type: string
+ * description: ID del cliente a actualizar.
+ * example: "123"
+ * nombreLegal:
+ * type: string
+ * description: Nuevo nombre legal del cliente.
+ * example: "Altertex S.A. de C.V."
+ * nombreComercial:
+ * type: string
+ * description: Nuevo nombre comercial del cliente.
+ * example: "Altertex Textiles"
+ * imagen:
+ * type: string
+ * format: binary
+ * description: Imagen nueva del cliente (opcional).
+ * responses:
+ * 200:
+ * description: Cliente actualizado exitosamente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Cliente actualizado correctamente.
+ * 400:
+ * description: Formato inválido del ID del cliente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: ID del cliente con formato inválido.
+ * 403:
+ * description: Permisos insuficientes o token inválido
+ * 500:
+ * description: Error del servidor al actualizar el cliente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Ocurrió un error al actualizar el cliente.
+ */
+ruteador.put(
+ RUTAS.CLIENTES.ACTUALIZAR,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.ACTUALIZAR_CLIENTE),
+ validarYSanitizar,
+ upload.single('imagen'),
+ controlador.actualizarClientes
+);
+
+module.exports = ruteador;
diff --git a/Clientes/Rutas/RutasIndividuales/consultarClientes.routes.js b/Clientes/Rutas/RutasIndividuales/consultarClientes.routes.js
new file mode 100644
index 00000000..1fdd80dc
--- /dev/null
+++ b/Clientes/Rutas/RutasIndividuales/consultarClientes.routes.js
@@ -0,0 +1,83 @@
+const express = require("express");
+const ruteador = express.Router();
+const controlador = require("@altertex/cli/ctrl/consultarClientes.controller");
+const revisarApiKey = require("@altertex/util/inter/revisarApiKey");
+const autorizarToken = require("@altertex/util/inter/autorizarToken");
+const verificarPermisos = require("@altertex/util/inter/verificarPermisos");
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+const PERMISOS = require("@altertex/util/const/permisos");
+const RUTAS = require("@altertex/util/const/rutas");
+
+/**
+ * RF12 - Consulta Lista de Clientes - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF12
+ */
+
+/**
+ * @swagger
+ * /api/clientes/consultar-lista:
+ * get:
+ * summary: Consultar lista de clientes asociados al usuario autenticado
+ * tags: [Clientes]
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * responses:
+ * 200:
+ * description: Lista de clientes obtenida exitosamente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Lista de clientes obtenida exitosamente.
+ * clientes:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * idCliente:
+ * type: integer
+ * example: 2
+ * nombreComercial:
+ * type: string
+ * example: Toyota Motors México
+ * nombreFiscal:
+ * type: string
+ * example: Toyota de México, S.A. de C.V.
+ * idImagen:
+ * type: integer
+ * example: 1
+ * urlImagen:
+ * type: string
+ * format: uri
+ * example: https://altertex.s3.us-east-2.amazonaws.com/clientes/toyota.jpg?... (URL firmada)
+ * tipoImagen:
+ * type: string
+ * example: Logo
+ * textoAlternativo:
+ * type: string
+ * example: Logo de Toyota Motors México
+ * 400:
+ * description: Datos inválidos o lista vacía
+ * 401:
+ * description: No autorizado, token o API key inválida
+ * 403:
+ * description: No tiene permisos para consultar clientes
+ * 500:
+ * description: Error interno al consultar los clientes
+ */
+
+ruteador.get(
+ RUTAS.CLIENTES.CONSULTAR_LISTA,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CONSULTAR_CLIENTES),
+ controlador.consultarLista
+);
+
+module.exports = ruteador;
diff --git a/Clientes/Rutas/RutasIndividuales/consultarSistema.routes.js b/Clientes/Rutas/RutasIndividuales/consultarSistema.routes.js
new file mode 100644
index 00000000..304c0c1f
--- /dev/null
+++ b/Clientes/Rutas/RutasIndividuales/consultarSistema.routes.js
@@ -0,0 +1,71 @@
+const express = require("express");
+const ruteador = express.Router();
+const controlador = require("@altertex/cli/ctrl/consultarSistema.controller");
+const revisarApiKey = require("@altertex/util/inter/revisarApiKey");
+const autorizarToken = require("@altertex/util/inter/autorizarToken");
+const verificarPermisos = require("@altertex/util/inter/verificarPermisos");
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+const PERMISOS = require("@altertex/util/const/permisos");
+const RUTAS = require("@altertex/util/const/rutas");
+
+/**
+ * @swagger
+ * /api/clientes/consultar-sistema:
+ * post:
+ * summary: Consultar sistema administrativo del cliente y emitir nuevo token
+ * tags: [Clientes]
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * required:
+ * - idCliente
+ * properties:
+ * idCliente:
+ * type: integer
+ * example: 1
+ * responses:
+ * 200:
+ * description: Consulta exitosa y nuevo token emitido
+ * headers:
+ * Set-Cookie:
+ * description: Token JWT actualizado para el cliente seleccionado
+ * schema:
+ * type: string
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Sistema consultado exitosamente.
+ * 400:
+ * description: Formato de ID de cliente inválido
+ * 401:
+ * description: No autorizado, token o API key inválida
+ * 403:
+ * description: El usuario no tiene acceso a ese cliente
+ * 404:
+ * description: El cliente no tiene sistema asociado
+ * 500:
+ * description: Error interno al consultar el sistema
+ */
+
+ruteador.post(
+ RUTAS.CLIENTES.CONSULTAR_SISTEMA,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CONSULTAR_SISTEMA_ADMINISTRATIVO),
+ controlador.consultarSistema
+);
+
+module.exports = ruteador;
diff --git a/Clientes/Rutas/RutasIndividuales/crearCliente.routes.js b/Clientes/Rutas/RutasIndividuales/crearCliente.routes.js
new file mode 100644
index 00000000..2cde7760
--- /dev/null
+++ b/Clientes/Rutas/RutasIndividuales/crearCliente.routes.js
@@ -0,0 +1,72 @@
+/**
+ * RF11 - Crear Cliente - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF11
+ */
+
+/**
+ * @swagger
+ * /api/clientes/crear-cliente:
+ * post:
+ * summary: Crear un nuevo cliente
+ * tags: [Clientes]
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * parameters:
+ * - in: body
+ * name: nombreComercial
+ * required: true
+ * schema:
+ * type: integer
+ * description: Nombre comercial del cliente que se quiere crear.
+ * responses:
+ * 201:
+ * description: Cliente creado exitosamente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Cliente creado.
+ * 400:
+ * description: Error al validar los datos.
+ * 401:
+ * description: No autorizado, token o API key inválida
+ * 403:
+ * description: No tiene permisos para crear clientes
+ * 500:
+ * description: Error interno al crear el cliente
+ */
+
+const express = require('express');
+const ruteador = express.Router();
+const multer = require('multer');
+const controlador = require('@altertex/cli/ctrl/crearCliente.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const validarYSanitizarImagen = require('@altertex/util/inter/validarYSanitizarImagen');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+// Configuración de multer para manejar archivos en memoria
+const storage = multer.memoryStorage();
+const upload = multer({ storage });
+
+ruteador.post(
+ RUTAS.CLIENTES.CREAR_CLIENTE,
+ upload.single('imagen'),
+ validarYSanitizar,
+ validarYSanitizarImagen(),
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CREAR_CLIENTE),
+ controlador.crearCliente
+);
+
+module.exports = ruteador;
diff --git a/Clientes/Rutas/RutasIndividuales/eliminarCliente.routes.js b/Clientes/Rutas/RutasIndividuales/eliminarCliente.routes.js
new file mode 100644
index 00000000..bd0e0b0d
--- /dev/null
+++ b/Clientes/Rutas/RutasIndividuales/eliminarCliente.routes.js
@@ -0,0 +1,59 @@
+/**
+ * RF15 - Elimina Cliente - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF15
+ */
+
+/**
+ * @swagger
+ * /api/clientes/eliminar:
+ * post:
+ * summary: Eliminar un cliente registrado
+ * tags: [Clientes]
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * parameters:
+ * - idCliente: int
+ * required: true
+ * schema:
+ * type: integer
+ * description: ID del cliente que se desea eliminar
+ * responses:
+ * 200:
+ * description: Cliente eliminado exitosamente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Cliente eliminado
+ * 404:
+ * description: No se encontró un cliente con el ID proporcionado.
+ * 400:
+ * description: Error interno al eliminar el cliente
+ */
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/cli/ctrl/eliminarCliente.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+ruteador.post(
+ RUTAS.CLIENTES.ELIMINAR_CLIENTE,
+ validarYSanitizar,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.ELIMINAR_CLIENTE),
+ controlador.eliminarCliente
+);
+
+module.exports = ruteador;
\ No newline at end of file
diff --git a/Clientes/Rutas/RutasIndividuales/leerCliente.routes.js b/Clientes/Rutas/RutasIndividuales/leerCliente.routes.js
new file mode 100644
index 00000000..803bae07
--- /dev/null
+++ b/Clientes/Rutas/RutasIndividuales/leerCliente.routes.js
@@ -0,0 +1,102 @@
+/**
+ * RF13 - Consulta Cliente - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/rf13/
+ */
+
+/**
+ * @swagger
+ * /api/clientes/consultar-cliente:
+ * post:
+ * summary: Consulta la información de un cliente específico.
+ * description: |
+ * Este endpoint permite consultar los datos de un cliente por su ID.
+ * tags: [Clientes]
+ * security:
+ * - ApiKeyAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * idCliente:
+ * type: integer
+ * example: 1
+ * required:
+ * - idCliente
+ * responses:
+ * 200:
+ * description: Cliente encontrado exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Información del cliente obtenida exitosamente."
+ * cliente:
+ * type: object
+ * properties:
+ * idCliente:
+ * type: integer
+ * example: 1
+ * nombreLegal:
+ * type: string
+ * example: "Toyota Motors Corporation"
+ * nombreVisible:
+ * type: string
+ * example: "Toyota"
+ * empleados:
+ * type: integer
+ * example: 1902
+ * usuariosAsignados:
+ * type: integer
+ * example: 5
+ * imagenCliente:
+ * type: string
+ * example: "https://example.com/logo-toyota.png"
+ * 404:
+ * description: Cliente no encontrado.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "No se encontró un cliente con el ID proporcionado."
+ * 400:
+ * description: Error interno del servidor al consultar el cliente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Ocurrió un error al obtener los datos del cliente."
+ */
+
+const express = require("express");
+const ruteador = express.Router();
+const controlador = require("@altertex/cli/ctrl/leerCliente.controller");
+const revisarApiKey = require("@altertex/util/inter/revisarApiKey");
+const autorizarToken = require("@altertex/util/inter/autorizarToken");
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const verificarPermisos = require("@altertex/util/inter/verificarPermisos");
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+const PERMISOS = require("@altertex/util/const/permisos");
+const RUTAS = require("@altertex/util/const/rutas");
+
+ruteador.post(
+ RUTAS.CLIENTES.LEER,
+ validarYSanitizar,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.LEER_CLIENTE),
+ controlador.leerCliente
+);
+
+module.exports = ruteador;
\ No newline at end of file
diff --git a/Clientes/Rutas/indexClientes.routes.js b/Clientes/Rutas/indexClientes.routes.js
new file mode 100644
index 00000000..8ea2aab6
--- /dev/null
+++ b/Clientes/Rutas/indexClientes.routes.js
@@ -0,0 +1,24 @@
+const express = require('express');
+const ruteador = express.Router();
+const rutasConsultarSistema = require("@altertex/cli/rutasInd/consultarSistema.routes");
+const rutasConsultarClientes = require("@altertex/cli/rutasInd/consultarClientes.routes");
+const rutasEliminarCliente = require("@altertex/cli/rutasInd/eliminarCliente.routes");
+const rutasCrearCliente = require("@altertex/cli/rutasInd/crearCliente.routes");
+const rutasActualizarCliente = require('@altertex/cli/rutasInd/actualizarClientes.routes');
+const rutasLeerCliente = require('@altertex/cli/rutasInd/leerCliente.routes');
+
+const RUTAS = require('@altertex/util/const/rutas');
+
+ruteador.use(RUTAS.CLIENTES.BASE, rutasConsultarSistema);
+//RF12 - Consulta Lista de Clientes - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF12
+ruteador.use(RUTAS.CLIENTES.BASE, rutasConsultarClientes);
+//RF15 - Elimina Cliente - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF15
+ruteador.use(RUTAS.CLIENTES.BASE, rutasEliminarCliente);
+
+//RF13 - Consulta Cliente - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/rf13/
+ruteador.use(RUTAS.CLIENTES.BASE, rutasLeerCliente);
+//RF11 - Crear Cliente - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF11
+ruteador.use(RUTAS.CLIENTES.BASE, rutasCrearCliente);
+
+ruteador.use(RUTAS.CLIENTES.BASE, rutasActualizarCliente);
+module.exports = ruteador;
diff --git a/Configuracion/clienteRedis.js b/Configuracion/clienteRedis.js
new file mode 100644
index 00000000..5f5f3a76
--- /dev/null
+++ b/Configuracion/clienteRedis.js
@@ -0,0 +1,10 @@
+const { createClient } = require('redis');
+
+const redis = createClient({
+ url: process.env.REDIS_URL,
+});
+
+redis.on('error', (err) => console.error('Error Redis', err));
+redis.connect();
+
+module.exports = redis;
\ No newline at end of file
diff --git a/Configuracion/corsOptions.js b/Configuracion/corsOptions.js
new file mode 100644
index 00000000..b3e7ebd7
--- /dev/null
+++ b/Configuracion/corsOptions.js
@@ -0,0 +1,5 @@
+module.exports = {
+ origin: [process.env.LOCAL_URL, process.env.DEPLOYED_URL],
+ methods: ["GET", "POST", "PUT", "DELETE"],
+ credentials: true,
+};
diff --git a/Configuracion/dotenv.js b/Configuracion/dotenv.js
new file mode 100644
index 00000000..ce300906
--- /dev/null
+++ b/Configuracion/dotenv.js
@@ -0,0 +1,5 @@
+const dotenv = require("dotenv");
+const camino = require("path");
+
+const archivoEnv = `.env.${process.env.NODE_ENV || "staging"}`;
+dotenv.config({ path: camino.resolve(process.cwd(), archivoEnv) });
diff --git a/Configuracion/rutasSwagger.js b/Configuracion/rutasSwagger.js
new file mode 100644
index 00000000..b7982bb0
--- /dev/null
+++ b/Configuracion/rutasSwagger.js
@@ -0,0 +1,58 @@
+module.exports = [
+ './Autenticacion/Rutas/RutasIndividuales/autenticacionSesion.routes.js',
+ './Autenticacion/Rutas/RutasIndividuales/cerrarSesion.routes.js',
+ './Autenticacion/Rutas/RutasIndividuales/inicioSesion.routes.js',
+
+ './Categorias/Rutas/RutasIndividuales/consultarListaCategorias.routes.js',
+ './Categorias/Rutas/RutasIndividuales/crearCategoria.routes.js',
+ './Categorias/Rutas/RutasIndividuales/eliminarCategoria.routes.js',
+
+ './Clientes/Rutas/RutasIndividuales/consultarClientes.routes.js',
+ './Clientes/Rutas/RutasIndividuales/consultarSistema.routes.js',
+ './Clientes/Rutas/RutasIndividuales/eliminarCliente.routes.js',
+ './Clientes/Rutas/RutasIndividuales/leerCliente.routes.js',
+ './Clientes/Rutas/RutasIndividuales/actualizarClientes.routes.js',
+ './Clientes/Rutas/RutasIndividuales/crearCliente.routes.js',
+
+ './Cuotas/Rutas/RutasIndividuales/consultarCuotas.routes.js',
+ './Cuotas/Rutas/RutasIndividuales/crearCuota.routes.js',
+ './Cuotas/Rutas/RutasIndividuales/eliminarSetCuotas.routes.js',
+ './Cuotas/Rutas/RutasIndividuales/obtenerOpcionesCuotas.routes.js',
+
+ './Empleados/Rutas/RutasIndividuales/consultarLista.routes.js',
+ './Empleados/Rutas/RutasIndividuales/consultarListaGrupos.routes.js',
+ './Empleados/Rutas/RutasIndividuales/eliminarEmpleado.routes.js',
+ './Empleados/Rutas/RutasIndividuales/eliminarGrupoEmpleados.routes.js',
+ './Empleados/Rutas/RutasIndividuales/leerGrupoEmpleados.routes.js',
+ './Empleados/Rutas/RutasIndividuales/importarEmpleados.routes.js',
+ './Empleados/Rutas/RutasIndividuales/crearGrupoEmpleados.routes.js',
+ './Empleados/Rutas/RutasIndividuales/actualizarEmpleado.routes.js',
+
+ './Eventos/Rutas/RutasIndividuales/consultarListaEventos.routes.js',
+ './Eventos/Rutas/RutasIndividuales/consultarEvento.routes.js',
+ './Eventos/Rutas/RutasIndividuales/eliminarEvento.routes.js',
+
+ './Pagos/Rutas/RutasIndividuales/consultarTipoPago.routes.js',
+ './Pagos/Rutas/RutasIndividuales/actualizarTipoPago.routes.js',
+
+ './Pedidos/Rutas/RutasIndividuales/eliminarPedidos.routes.js',
+ './Pedidos/Rutas/RutasIndividuales/obtenerPedidos.routes.js',
+
+ './Productos/Rutas/RutasIndividuales/consultarProductos.routes.js',
+ './Productos/Rutas/RutasIndividuales/crearProducto.routes.js',
+ './Productos/Rutas/RutasIndividuales/eliminarProducto.routes.js',
+
+ './Roles/Rutas/RutasIndividuales/consultarLista.routes.js',
+ './Roles/Rutas/RutasIndividuales/crearRol.routes.js',
+ './Roles/Rutas/RutasIndividuales/eliminarRol.routes.js',
+ './Roles/Rutas/RutasIndividuales/obtenerOpcionesRol.routes.js',
+
+ './SetsProductos/Rutas/RutasIndividuales/consultarSetsProductos.routes.js',
+ './SetsProductos/Rutas/RutasIndividuales/eliminarSetsProductos.routes.js',
+ './SetsProductos/Rutas/RutasIndividuales/crearSetsProductos.routes.js',
+
+ './Usuarios/Rutas/RutasIndividuales/consultarListaUsuarios.routes.js',
+ './Usuarios/Rutas/RutasIndividuales/crearUsuario.routes.js',
+ './Usuarios/Rutas/RutasIndividuales/eliminarUsuario.routes.js',
+ './Usuarios/Rutas/RutasIndividuales/leerUsuario.routes.js',
+];
diff --git a/Configuracion/swagger.js b/Configuracion/swagger.js
new file mode 100644
index 00000000..a0ac74ad
--- /dev/null
+++ b/Configuracion/swagger.js
@@ -0,0 +1,21 @@
+const rutas = require('@altertex/config/rutasSwagger');
+
+const opcionesSwagger = {
+ definition: {
+ openapi: '3.0.0',
+ info: {
+ title: 'API de TEXT&LINES',
+ version: '1.0.0',
+ description: 'Documentación de la API para TEXT&LINES',
+ },
+ servers: [
+ {
+ url: process.env.LOCAL_URL_BACKEND || 'http://localhost:5000',
+ },
+ ],
+ },
+
+ apis: rutas,
+};
+
+module.exports = opcionesSwagger;
diff --git a/Cuotas/Controladores/actualizarSetCuotas.controller.js b/Cuotas/Controladores/actualizarSetCuotas.controller.js
new file mode 100644
index 00000000..7c5ae1da
--- /dev/null
+++ b/Cuotas/Controladores/actualizarSetCuotas.controller.js
@@ -0,0 +1,24 @@
+const repositorio = require('@altertex/cuota/repos/actualizarSetCuotasRepositorio');
+
+/**
+ * Controlador que gestiona la actualización de un set de cuotas.
+ *
+ * @param {object} req - Objeto de solicitud HTTP de Express.
+ * @param {object} res - Objeto de respuesta HTTP de Express.
+ * @returns {object} Respuesta JSON con el resultado de la operación.
+ */
+exports.actualizarSetCuotas = async (req, res) => {
+ try {
+ const { idCuotaSet, cambios } = req.body;
+
+ if (!idCuotaSet || !cambios) {
+ return res.status(400).json({ mensaje: 'Datos incompletos' });
+ }
+
+ await repositorio.actualizarSetCuotas(idCuotaSet, cambios);
+ return res.status(200).json({ mensaje: 'Set de cuotas actualizado correctamente' });
+
+ } catch (error) {
+ return res.status(500).json({ mensaje: error.message });
+ }
+};
diff --git a/Cuotas/Controladores/consultarListasCuotas.controller.js b/Cuotas/Controladores/consultarListasCuotas.controller.js
new file mode 100644
index 00000000..bb89bb37
--- /dev/null
+++ b/Cuotas/Controladores/consultarListasCuotas.controller.js
@@ -0,0 +1,49 @@
+const repositorio = require('@altertex/cuota/repos/cuotasRepositorio');
+const MENSAJES_CUOTAS = require('@altertex/util/const/mensajesCuotas');
+
+/**
+ * Controlador para consultar la lista de sets de cuotas.
+ *
+ * RF32 - Consulta Lista de Sets de Cuotas - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF32
+ *
+ * @async
+ * @function consultarLista
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.user - Datos del usuario autenticado.
+ * @param {number} req.user.clienteSeleccionado - ID del cliente autenticado.
+ * @param {object} res - Objeto de respuesta de Express.
+ *
+ * @returns {Response} Respuesta HTTP con:
+ * - 200 si la consulta fue exitosa.
+ * - 204 si no hay resultados.
+ * - 400 si falta el ID del cliente.
+ * - 500 si hay error en el servidor.
+ */
+exports.consultarLista = async (req, res) => {
+ const idCliente = parseInt(req.user.clienteSeleccionado);
+
+ if (!idCliente) {
+ return res
+ .status(MENSAJES_CUOTAS.PARAMETROS_INVALIDOS.codigo)
+ .json({ mensaje: MENSAJES_CUOTAS.PARAMETROS_INVALIDOS.mensaje });
+ }
+
+ try {
+ const resultados = await repositorio.obtenerCuotas(idCliente);
+
+ if (!resultados || resultados.length === 0) {
+ return res
+ .status(MENSAJES_CUOTAS.SIN_RESULTADOS.codigo)
+ .json({ mensaje: MENSAJES_CUOTAS.SIN_RESULTADOS.mensaje });
+ }
+
+ return res.status(MENSAJES_CUOTAS.CONSULTA_EXITOSA.codigo).json({
+ mensaje: MENSAJES_CUOTAS.CONSULTA_EXITOSA.mensaje,
+ cuotas: resultados,
+ });
+ } catch {
+ return res
+ .status(MENSAJES_CUOTAS.ERROR_CONSULTAR_CUOTAS.codigo)
+ .json({ mensaje: MENSAJES_CUOTAS.ERROR_CONSULTAR_CUOTAS.mensaje });
+ }
+};
diff --git a/Cuotas/Controladores/crearCuota.controller.js b/Cuotas/Controladores/crearCuota.controller.js
new file mode 100644
index 00000000..22569040
--- /dev/null
+++ b/Cuotas/Controladores/crearCuota.controller.js
@@ -0,0 +1,69 @@
+const { validarCuotaSet } = require('@altertex/cuota/ctrl/validarCuotaSet');
+const repositorio = require('@altertex/cuota/repos/crearCuotaRepositorio');
+const MENSAJES = require('@altertex/util/const/mensajesCuotas');
+
+/**
+ * RF31 - Crear Cuotas - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF31
+ *
+ * Controlador para crear un nuevo conjunto de cuotas (cuotaSet) desde el frontend.
+ *
+ * - Valida que el cuerpo de la solicitud tenga el formato correcto
+ * - Valida nombre y productos usando la función `validarCuotaSet`
+ * - Agrega automáticamente la fecha de creación y el ID del cliente autenticado
+ * - Llama al repositorio para persistir en la base de datos
+ *
+ * @function crearCuota
+ * @param {Express.Request} req - Objeto de solicitud HTTP
+ * @param {Express.Response} res - Objeto de respuesta HTTP
+ *
+ * @returns {Response} Respuesta HTTP con estado 201 si fue exitoso o 400 si falló
+ */
+exports.crearCuota = async (req, res) => {
+ const cuotaSetModelo = req.body;
+
+ try {
+ if (!cuotaSetModelo || typeof cuotaSetModelo !== 'object') {
+ return res.status(400).json({ error: MENSAJES.FORMATO_INVALIDO });
+ }
+
+ if (!cuotaSetModelo.nombre || cuotaSetModelo.nombre.trim() === '') {
+ return res.status(400).json({ error: MENSAJES.NOMBRE_OBLIGATORIO });
+ }
+
+ let errorValidacion = null;
+ try {
+ errorValidacion = validarCuotaSet(
+ cuotaSetModelo.nombre,
+ cuotaSetModelo.productosYLimite,
+ res
+ );
+ } catch (err) {
+ return res.status(400).json({
+ error: 'Error creando cuota set',
+ detalle: err.message || err,
+ });
+ }
+
+ if (errorValidacion) {
+ return res.status(400).json({
+ error: errorValidacion,
+ contexto: 'Error al validar los datos del set de cuotas. Verifica los campos enviados.',
+ });
+ }
+
+ const hoy = new Date();
+ const fechaFormateada = hoy.toISOString().split('T')[0];
+
+ cuotaSetModelo.ultimaActualizacion = fechaFormateada;
+ cuotaSetModelo.idCliente = req.user.clienteSeleccionado;
+
+ await repositorio.crearCuota(cuotaSetModelo);
+
+ return res.status(201).json({ exito: MENSAJES.CREACION_EXITOSA });
+ } catch (error) {
+ return res.status(400).json({
+ error: MENSAJES.ERROR_CREACION,
+ detalle: error.message || error,
+ });
+ }
+};
diff --git a/Cuotas/Controladores/eliminarSetCuotas.controller.js b/Cuotas/Controladores/eliminarSetCuotas.controller.js
new file mode 100644
index 00000000..0cbeff99
--- /dev/null
+++ b/Cuotas/Controladores/eliminarSetCuotas.controller.js
@@ -0,0 +1,49 @@
+const repositorio = require('@altertex/cuota/repos/eliminarSetCuotasRepositorio');
+const MENSAJES_SET_CUOTAS = require('@altertex/util/const/mensajesCuotas');
+
+/**
+ * Controlador para eliminar uno o varios sets de cuotas.
+ *
+ * RF[35] - Super Administrador elimina Set de Cuotas
+ * https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF35
+ *
+ * @async
+ * @function eliminarSetCuotas
+ * @param {object} req - Objeto de solicitud HTTP.
+ * @param {object} req.body - Cuerpo de la solicitud, debe incluir un arreglo `idsSetCuotas`.
+ * @param {object} res - Objeto de respuesta HTTP.
+ *
+ * @returns {Response} Devuelve un estado:
+ * - 200 si la eliminación fue exitosa.
+ * - 404 si no se encontraron IDs válidos.
+ * - 500 si ocurrió un error interno.
+ */
+exports.eliminarSetCuotas = async (req, res) => {
+ try {
+ const idsSetCuotas = req.body.idsSetCuotas;
+
+ if (!Array.isArray(idsSetCuotas) || idsSetCuotas.length === 0) {
+ return res.status(MENSAJES_SET_CUOTAS.SET_CUOTA_NO_ENCONTRADO.codigo).json({
+ mensaje: MENSAJES_SET_CUOTAS.SET_CUOTA_NO_ENCONTRADO.mensaje,
+ });
+ }
+
+ await Promise.all(
+ idsSetCuotas.map(async (idSetCuota) => {
+ const resultadoSetCuotas = await repositorio.eliminarSetCuotas(idSetCuota);
+
+ if (resultadoSetCuotas.affectedRows === 0) {
+ throw new Error(`Set de cuotas con ID ${idSetCuota} no encontrado`);
+ }
+ })
+ );
+
+ return res.status(MENSAJES_SET_CUOTAS.SET_CUOTA_ELIMINADO.codigo).json({
+ mensaje: MENSAJES_SET_CUOTAS.SET_CUOTA_ELIMINADO.mensaje,
+ });
+ } catch {
+ return res.status(MENSAJES_SET_CUOTAS.ERROR_ELIMINAR_SET_CUOTAS.codigo).json({
+ mensaje: MENSAJES_SET_CUOTAS.ERROR_ELIMINAR_SET_CUOTAS.mensaje,
+ });
+ }
+};
diff --git a/Cuotas/Controladores/leerSetCuotas.controller.js b/Cuotas/Controladores/leerSetCuotas.controller.js
new file mode 100644
index 00000000..9c33418d
--- /dev/null
+++ b/Cuotas/Controladores/leerSetCuotas.controller.js
@@ -0,0 +1,44 @@
+const repositorio = require('@altertex/cuota/repos/leerSetCuotasRepositorio');
+const MENSAJES_CUOTAS = require('@altertex/util/const/mensajesCuotas');
+
+/**
+ * Lee un conjunto de cuotas desde la base de datos utilizando su ID.
+ *
+ * Valida el parámetro `idSetCuota` y obtiene la información del set de cuotas a través del repositorio.
+ * Si el set de cuotas no es encontrado o el parámetro es inválido, retorna un error.
+ *
+ * @param {Express.Request} req - La solicitud HTTP que contiene el `idSetCuota` en el cuerpo.
+ * @param {Express.Response} res - La respuesta HTTP para enviar el resultado al cliente.
+ * @returns {Promise} Responde con el set de cuotas encontrado o un mensaje de error.
+ *
+ * @see [RF33] Leer set cuotas(https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF33)
+ */
+exports.leerSetCuotas = async (req, res) => {
+ const idSetCuota = parseInt(req.body.idSetCuota);
+
+ if (isNaN(idSetCuota)) {
+ return res
+ .status(MENSAJES_CUOTAS.PARAMETROS_INVALIDOS.codigo)
+ .json({ mensaje: MENSAJES_CUOTAS.PARAMETROS_INVALIDOS.mensaje });
+ }
+
+ try {
+ const setCuota = await repositorio.obtenerSetCuotaPorId(idSetCuota);
+
+ if (!setCuota) {
+ return res
+ .status(MENSAJES_CUOTAS.SET_CUOTA_NO_ENCONTRADO.codigo)
+ .json({ mensaje: MENSAJES_CUOTAS.SET_CUOTA_NO_ENCONTRADO.mensaje });
+ }
+
+ return res.status(MENSAJES_CUOTAS.CONSULTA_EXITOSA.codigo).json({
+ mensaje: MENSAJES_CUOTAS.CONSULTA_EXITOSA.mensaje,
+ setCuota,
+ });
+ } catch (error) {
+ console.error('Error al consultar Set cuotas:', error);
+ return res
+ .status(MENSAJES_CUOTAS.ERROR_OBTENER_SET_CUOTA.codigo)
+ .json({ mensaje: MENSAJES_CUOTAS.ERROR_OBTENER_SET_CUOTA.mensaje });
+ }
+};
diff --git a/Cuotas/Controladores/obtenerOpcionesCuotas.controller.js b/Cuotas/Controladores/obtenerOpcionesCuotas.controller.js
new file mode 100644
index 00000000..835fe72b
--- /dev/null
+++ b/Cuotas/Controladores/obtenerOpcionesCuotas.controller.js
@@ -0,0 +1,28 @@
+const repositorio = require('@altertex/cuota/repos/obtenerOpcionesCuotasRepositorio');
+const MENSAJES = require('@altertex/util/const/mensajesCuotas');
+
+/**
+ * Obtiene las opciones de cuota disponibles para un cliente.
+ *
+ * Este controlador se encarga de recibir la solicitud para obtener las opciones de cuota para un cliente,
+ * verificando primero que el `idCliente` esté presente en la solicitud. Luego, llama a un repositorio para
+ * obtener las opciones de cuota. Si ocurre un error o falta el `idCliente`, se responde con un mensaje de error.
+ *
+ * @param {object} req - El objeto de solicitud que contiene el `idCliente` en su cuerpo.
+ * @param {object} res - El objeto de respuesta para enviar el resultado o el error.
+ * @returns {Promise} No devuelve valor explícito. Envía una respuesta con el estado adecuado.
+ */
+exports.obtenerOpcionesCuotas = async (req, res) => {
+ try {
+ const idCliente = req.body.clienteSeleccionado;
+ if (!idCliente) {
+ return res.status(400).json({ mensaje: MENSAJES.FALTA_ID_CLIENTE });
+ }
+
+ const resultado = await repositorio.obtenerCuotaOpcion(idCliente);
+
+ return res.status(201).json({ mensaje: MENSAJES.OPCIONES_OBTENIDAS, resultado });
+ } catch (error) {
+ return res.status(400).json({ mensaje: MENSAJES.ERROR_OBTENIENDO_OPCIONES, error });
+ }
+};
diff --git a/Cuotas/Controladores/validarCuotaSet.js b/Cuotas/Controladores/validarCuotaSet.js
new file mode 100644
index 00000000..8e82e4b6
--- /dev/null
+++ b/Cuotas/Controladores/validarCuotaSet.js
@@ -0,0 +1,70 @@
+/**
+ *
+ * RF31 - Crear Cuotas - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF31
+ *
+ * Valida los datos de un conjunto de cuotas (cuotaSet), asegurando que el nombre
+ * y la lista de productos con sus respectivos límites sean válidos.
+ *
+ * Esta función lanza errores HTTP utilizando `res.status().json()` si detecta
+ * algún problema en los datos recibidos.
+ *
+ * @function validarCuotaSet
+ * @param {string} nombre - Nombre del conjunto de cuotas.
+ * @param {Array} productosYLimite - Lista de productos con sus límites.
+ * @param {string} productosYLimite[].idProducto - ID del producto.
+ * @param {number} productosYLimite[].limite - Límite máximo asignado al producto.
+ * @param {number} productosYLimite[].limiteActual - Límite actual usado del producto.
+ * @returns {void}
+ *
+ * @throws Retorna una respuesta HTTP 400 si:
+ * - El nombre es inválido.
+ * - La lista de productos está vacía o mal formada.
+ * - Algún producto tiene campos inválidos.
+ *
+ * @note Esta función depende implícitamente de `res`, pero no se pasa como parámetro.
+ * Para que sea reutilizable, se recomienda lanzar errores o retornar un objeto de error en lugar de usar `res` directamente.
+ */
+const MENSAJES = require('@altertex/util/const/mensajesCuotas');
+
+function validarCuotaSet(nombre, productosYLimite) {
+ if (!nombre || typeof nombre !== 'string' || nombre.trim() === '') {
+ return MENSAJES.NOMBRE_REQUERIDO;
+ }
+
+ if (!Array.isArray(productosYLimite) || productosYLimite.length === 0) {
+ return MENSAJES.PRODUCTOS_REQUERIDOS;
+ }
+
+ for (let iterador = 0; iterador < productosYLimite.length; iterador += 1) {
+ const { idProducto, limite, limiteActual } = productosYLimite[iterador];
+
+ if (!idProducto || typeof idProducto !== 'string' || idProducto.trim() === '') {
+ return MENSAJES.ID_PRODUCTO_INVALIDO(iterador);
+ }
+
+ // Rechazar strings numéricos con ceros a la izquierda
+ if (
+ (typeof limite === 'string' && /^0[0-9]+$/.test(limite))
+ || (typeof limiteActual === 'string' && /^0[0-9]+$/.test(limiteActual))
+ ) {
+ return 'No se permiten ceros a la izquierda en los valores de cuota.';
+ }
+
+ if (typeof limite !== 'number' || isNaN(limite) || !Number.isInteger(limite) || limite <= 0) {
+ return MENSAJES.LIMITE_INVALIDO(idProducto);
+ }
+
+ if (
+ typeof limiteActual !== 'number'
+ || isNaN(limiteActual)
+ || !Number.isInteger(limiteActual)
+ || limiteActual <= 0
+ ) {
+ return MENSAJES.LIMITE_ACTUAL_INVALIDO(idProducto);
+ }
+ }
+
+ return null;
+}
+
+module.exports = { validarCuotaSet };
diff --git a/Cuotas/Datos/Repositorios/actualizarSetCuotasRepositorio.js b/Cuotas/Datos/Repositorios/actualizarSetCuotasRepositorio.js
new file mode 100644
index 00000000..158b6a66
--- /dev/null
+++ b/Cuotas/Datos/Repositorios/actualizarSetCuotasRepositorio.js
@@ -0,0 +1,44 @@
+const CONSULTAS_CUOTAS = require('@altertex/util/const/consultasCuotas');
+const correrQuery = require('@altertex/util/ser/correrQuery');
+
+/**
+ * Actualiza un set de cuotas en la base de datos.
+ *
+ * @async
+ * @param {number} idCuotaSet - ID del set de cuotas a actualizar.
+ * @param {object} cambios - Objeto con los cambios a aplicar.
+ * @param {string} cambios.nombre - Nombre actualizado del set de cuotas.
+ * @param {string} cambios.descripcion - Descripción del set de cuotas.
+ * @param {number} cambios.periodoRenovacion - Periodo de renovación en meses.
+ * @param {boolean} cambios.renovacionHabilitada - Si la renovación está habilitada.
+ * @param {Array} [cambios.productos=[]] - Lista de productos con límites.
+ * @param {number} cambios.productos[].idProducto - ID del producto asociado.
+ * @param {number} cambios.productos[].limite - Límite asignado al producto.
+ * @param {number} cambios.productos[].limiteActual - Límite actual del producto.
+ * @throws {Error} Si ocurre un error en la consulta a la base de datos.
+ */
+exports.actualizarSetCuotas = async (idCuotaSet, cambios) => {
+ const { nombre, descripcion, periodoRenovacion, renovacionHabilitada, productos = [] } = cambios;
+
+ await correrQuery(CONSULTAS_CUOTAS.ACTUALIZAR_CUOTA_SET, [
+ nombre,
+ descripcion,
+ periodoRenovacion,
+ renovacionHabilitada,
+ new Date(),
+ idCuotaSet
+ ]);
+
+ await correrQuery(CONSULTAS_CUOTAS.ELIMINAR_PRODUCTOS_CUOTA_SET, [idCuotaSet]);
+
+ for (const producto of productos) {
+ if (producto.idProducto && producto.idProducto > 0) {
+ await correrQuery(CONSULTAS_CUOTAS.INSERTAR_CUOTA_PRODUCTO_ACTUALIZAR, [
+ idCuotaSet,
+ producto.idProducto,
+ producto.limite || 0,
+ producto.limiteActual || 0
+ ]);
+ }
+ }
+};
diff --git a/Cuotas/Datos/Repositorios/crearCuotaRepositorio.js b/Cuotas/Datos/Repositorios/crearCuotaRepositorio.js
new file mode 100644
index 00000000..c54e811c
--- /dev/null
+++ b/Cuotas/Datos/Repositorios/crearCuotaRepositorio.js
@@ -0,0 +1,130 @@
+const db = require('@altertex/util/bd/db');
+const QUERY = require('@altertex/util/const/consultasCuotas');
+
+/**
+ * RF31 - Crear Cuotas - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF31
+ *
+ * Crea un nuevo conjunto de cuotas (cuotaSet) en la base de datos.
+ *
+ * Esta función realiza una transacción que:
+ * - Inserta un nuevo registro en la tabla de cuotas (cuotaSet)
+ * - Asocia los productos con sus respectivos límites
+ * - Si algún producto tiene un `idProducto` no numérico, se busca en la base de datos
+ * - Si ocurre algún error, la transacción se revierte automáticamente
+ *
+ * @async
+ * @function crearCuota
+ * @param {object} data - Objeto que contiene la información del cuotaSet.
+ * @param {number} data.idCliente - ID del cliente al que pertenece el cuotaSet.
+ * @param {string} data.nombre - Nombre del conjunto de cuotas.
+ * @param {string} data.descripcion - Descripción del conjunto de cuotas.
+ * @param {string} data.periodoRenovacion - Periodo de renovación (e.g., "mensual").
+ * @param {boolean} data.renovacionHabilitada - Si la renovación automática está habilitada.
+ * @param {Array} data.productosYLimite - Arreglo de productos con sus límites.
+ * @param {string|number} data.productosYLimite[].idProducto - ID numérico o código del producto.
+ * @param {number} data.productosYLimite[].limite - Límite máximo asignado.
+ * @param {number} data.productosYLimite[].limiteActual - Límite actual utilizado.
+ * @param {string} data.ultimaActualizacion - Fecha en formato YYYY-MM-DD.
+ *
+ * @returns {Promise} ID del nuevo cuotaSet creado.
+ *
+ * @throws {Error} Si faltan parámetros requeridos o falla la transacción.
+ */
+exports.crearCuota = async (data) => {
+ // Validaciones iniciales
+ if (
+ !data
+ || typeof data !== 'object'
+ || typeof data.idCliente !== 'number'
+ || typeof data.nombre !== 'string'
+ || typeof data.descripcion !== 'string'
+ || typeof data.periodoRenovacion !== 'number'
+ || typeof data.renovacionHabilitada !== 'boolean'
+ || !Array.isArray(data.productosYLimite)
+ || typeof data.ultimaActualizacion !== 'string'
+ ) {
+ throw new Error('Datos inválidos o incompletos para crear la cuota.');
+ }
+
+ // Validar estructura de cada producto
+ for (const item of data.productosYLimite) {
+ // Verifica si el valor original es string y tiene ceros a la izquierda
+ if (
+ (typeof item.limite === 'string' && /^0[0-9]+$/.test(item.limite))
+ || (typeof item.limiteActual === 'string' && /^0[0-9]+$/.test(item.limiteActual))
+ ) {
+ throw new Error('No se permiten ceros a la izquierda en los valores de cuota.');
+ }
+ if (
+ !item
+ || (typeof item.idProducto !== 'string' && typeof item.idProducto !== 'number')
+ || typeof item.limite !== 'number'
+ || !Number.isInteger(item.limite)
+ || item.limite <= 0
+ || typeof item.limiteActual !== 'number'
+ || !Number.isInteger(item.limiteActual)
+ || item.limiteActual <= 0
+ ) {
+ throw new Error(
+ 'Cada producto debe tener un idProducto (string o number), limite (entero > 0) y limiteActual (entero > 0).'
+ );
+ }
+ }
+
+ const conexion = await db.getConnection();
+
+ try {
+ await conexion.beginTransaction();
+
+ const {
+ nombre,
+ descripcion,
+ periodoRenovacion,
+ renovacionHabilitada,
+ productosYLimite,
+ ultimaActualizacion,
+ idCliente,
+ } = data;
+
+ const [resultado] = await conexion.execute(QUERY.INSERTAR_CUOTA, [
+ idCliente,
+ nombre,
+ descripcion,
+ periodoRenovacion,
+ renovacionHabilitada,
+ ultimaActualizacion,
+ ]);
+
+ const cuotaSetId = resultado.insertId;
+
+ for (const item of productosYLimite) {
+ let idProducto = item.idProducto;
+
+ if (isNaN(idProducto)) {
+ const [rows] = await conexion.execute(QUERY.SELECCIONAR_PRODUCTO, [idProducto]);
+
+ if (rows.length === 0) {
+ continue;
+ }
+
+ idProducto = rows[0].idProducto;
+ }
+
+ await conexion.execute(QUERY.INSERTAR_CUOTA_PRODUCTO, [
+ cuotaSetId,
+ idProducto,
+ item.limite,
+ item.limiteActual,
+ ]);
+ }
+
+ await conexion.commit();
+
+ return cuotaSetId;
+ } catch {
+ await conexion.rollback();
+ throw new Error('Error creando cuota set');
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
\ No newline at end of file
diff --git a/Cuotas/Datos/Repositorios/cuotasRepositorio.js b/Cuotas/Datos/Repositorios/cuotasRepositorio.js
new file mode 100644
index 00000000..0bca9b34
--- /dev/null
+++ b/Cuotas/Datos/Repositorios/cuotasRepositorio.js
@@ -0,0 +1,41 @@
+// Importación de la función utilitaria para ejecutar queries SQL hacia la base de datos.
+const correrQuery = require('@altertex/util/ser/correrQuery');
+
+// Importación del conjunto de consultas SQL relacionadas con la entidad "Cuotas".
+const CONSULTAS_CUOTAS = require('@altertex/util/const/consultasCuotas');
+
+/**
+ * Función encargada de obtener los sets de cuotas asociados a un cliente específico.
+ * RF32 - Consulta Lista de Sets de Cuotas - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF32
+ * @async
+ * @function obtenerCuotas
+ * @param {number} idCliente - Identificador único del cliente a consultar.
+ * @returns {Promise>} Retorna una lista de sets de cuotas si existen,
+ * o un array vacío si ocurre un error o no se encuentran resultados.
+ *
+ * @throws {Error} En caso de fallo en la ejecución de la consulta, se captura el error
+ * y se retorna una lista vacía. El error se registra en consola para facilitar depuración.
+ *
+ * @example
+ * const cuotas = await obtenerCuotas(42);
+ * console.log(cuotas); // [{ idCuota: 1, nombre: 'Mensualidad A', ... }, ...]
+ *
+ * @description
+ * Esta función forma parte del requerimiento funcional RF32 - "Consulta Lista de Sets de Cuotas".
+ * Realiza una consulta SQL utilizando `correrQuery`, pasando como parámetro el `idCliente`.
+ * Si no hay resultados o ocurre un error, retorna un array vacío como respuesta segura por defecto.
+ */
+exports.obtenerCuotas = async (idCliente) => {
+ try {
+ // Ejecuta la consulta SQL con el ID del cliente como parámetro.
+ const resultado = await correrQuery(CONSULTAS_CUOTAS.OBTENER_CUOTAS, [idCliente]);
+
+ // Retorna los resultados o un arreglo vacío si no hay datos.
+ return resultado || [];
+ } catch {
+ // Registra el error en consola para diagnóstico.
+
+ // Devuelve un array vacío en caso de error para evitar ruptura del flujo.
+ return [];
+ }
+};
diff --git a/Cuotas/Datos/Repositorios/eliminarSetCuotasRepositorio.js b/Cuotas/Datos/Repositorios/eliminarSetCuotasRepositorio.js
new file mode 100644
index 00000000..3879ce7d
--- /dev/null
+++ b/Cuotas/Datos/Repositorios/eliminarSetCuotasRepositorio.js
@@ -0,0 +1,46 @@
+const db = require('@altertex/util/bd/db');
+const CONSULTAS_CUOTAS = require('@altertex/util/const/consultasCuotas');
+
+/**
+ * Elimina un set de cuotas y sus relaciones con productos desde la base de datos.
+ *
+ * @async
+ * @function eliminarSetCuotas
+ * @param {number} idSetCuotas - ID del set de cuotas a eliminar.
+ * @returns {Promise} Objeto con mensaje de éxito y resultados de las operaciones SQL.
+ * @throws {Error} Si ocurre un error durante la transacción.
+ */
+exports.eliminarSetCuotas = async (idSetCuotas) => {
+ const conexion = await db.getConnection();
+
+ try {
+ await conexion.beginTransaction();
+
+ const [resultadoProductosSetCuotas] = await conexion.query(
+ CONSULTAS_CUOTAS.ELIMINAR_CUOTA_SET_PRODUCTO,
+ [idSetCuotas]
+ );
+
+ const [resultadoSetCuotas] = await conexion.query(
+ CONSULTAS_CUOTAS.ELIMINAR_CUOTA_SET,
+ [idSetCuotas]
+ );
+
+ if (resultadoSetCuotas.affectedRows === 0) {
+ throw new Error(`Set de cuotas con ID ${idSetCuotas} no encontrado`);
+ }
+
+ await conexion.commit();
+
+ return {
+ mensaje: 'Set de cuotas eliminado correctamente',
+ resultadoProductosSetCuotas,
+ resultadoSetCuotas,
+ };
+ } catch {
+ await conexion.rollback();
+ throw new Error('Error eliminando set de cuotas');
+ } finally {
+ conexion.release();
+ }
+};
\ No newline at end of file
diff --git a/Cuotas/Datos/Repositorios/leerSetCuotasRepositorio.js b/Cuotas/Datos/Repositorios/leerSetCuotasRepositorio.js
new file mode 100644
index 00000000..b939a7b6
--- /dev/null
+++ b/Cuotas/Datos/Repositorios/leerSetCuotasRepositorio.js
@@ -0,0 +1,55 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_CUOTAS = require('@altertex/util/const/consultasCuotas');
+
+/**
+ * Obtiene un conjunto de cuotas desde la base de datos mediante su ID.
+ *
+ * Ejecuta una consulta SQL y retorna el primer conjunto de cuotas encontrado o `null` si no existe.
+ *
+ * @param {number} idSetCuota - ID del set de cuotas a buscar.
+ * @returns {Promise} El conjunto de cuotas encontrado o `null` si no existe.
+ * @throws {Error} Si ocurre un error al ejecutar la consulta.
+ */
+exports.obtenerSetCuotaPorId = async (idSetCuota) => {
+
+ const query = CONSULTAS_CUOTAS.LEER_CUOTA_SET;
+ const queryCuotas = CONSULTAS_CUOTAS.LEER_CUOTA_SET_PRODUCTOS;
+
+ const resultado = await correrQuery(query, [idSetCuota]);
+
+ if (resultado.length === 0) return null;
+
+ const productosCuota = await correrQuery(queryCuotas, [idSetCuota]);
+
+ const productos = productosCuota.map((producto) => ({
+ idProducto: producto.idProducto,
+ nombre: producto.nombreComun,
+ nombreComun: producto.nombreComun,
+ cuota_valor: producto.cuota_valor,
+ limite_actual: producto.limite_actual,
+ valor: producto.cuota_valor,
+ limite: producto.cuota_valor,
+ limiteActual: producto.limite_actual
+ }));
+
+ const cuotas = productosCuota.map((producto) => ({
+ valor: producto.cuota_valor,
+ }));
+
+ const setCuota = {
+ idSetCuota: resultado[0].idCuotaSet,
+ idCuotaSet: resultado[0].idCuotaSet,
+
+ nombre: resultado[0].nombre,
+ descripcion: resultado[0].descripcion,
+
+ periodoRenovacion: resultado[0].periodoRenovacion,
+ renovacionHabilitada: resultado[0].renovacionHabilitada,
+ ultimaActualizacion: resultado[0].ultimaActualizacion,
+ productos,
+ cuotas,
+ };
+
+
+ return setCuota;
+};
\ No newline at end of file
diff --git a/Cuotas/Datos/Repositorios/obtenerOpcionesCuotasRepositorio.js b/Cuotas/Datos/Repositorios/obtenerOpcionesCuotasRepositorio.js
new file mode 100644
index 00000000..dbaf7703
--- /dev/null
+++ b/Cuotas/Datos/Repositorios/obtenerOpcionesCuotasRepositorio.js
@@ -0,0 +1,21 @@
+const QUERY = require('@altertex/util/const/consultasCuotas');
+const correrQuery = require('@altertex/util/ser/correrQuery');
+
+/**
+ * Obtiene las opciones de cuota disponibles para un cliente específico.
+ *
+ * Realiza una consulta a la base de datos usando el identificador de cliente (`idCliente`) para obtener las opciones de cuota
+ * asociadas a ese cliente. Si ocurre un error durante la ejecución de la consulta, se captura y se lanza un nuevo error.
+ *
+ * @param {number} idCliente - El ID del cliente para el cual se obtienen las opciones de cuota.
+ * @returns {Promise} Una promesa que resuelve con las opciones de cuota obtenidas de la base de datos.
+ * @throws {Error} Si ocurre un error durante la ejecución de la consulta.
+ */
+exports.obtenerCuotaOpcion = async (idCliente) => {
+ try {
+ const resultado = await correrQuery(QUERY.OBTENER_OPCIONES, [idCliente]);
+ return resultado;
+ } catch {
+ throw new Error('Error obteniendo opciones');
+ }
+};
diff --git a/Cuotas/Rutas/RutasIndividuales/actualizarSetCuotas.routes.js b/Cuotas/Rutas/RutasIndividuales/actualizarSetCuotas.routes.js
new file mode 100644
index 00000000..65860635
--- /dev/null
+++ b/Cuotas/Rutas/RutasIndividuales/actualizarSetCuotas.routes.js
@@ -0,0 +1,37 @@
+/**
+ * Ruta para actualizar un set de cuotas.
+ *
+ * Método: PUT
+ * Ruta: /api/cuotas/actualizar-set-cuotas (o la que defina `RUTAS.CUOTAS.ACTUALIZAR_SET_CUOTAS`)
+ *
+ * Middleware aplicados:
+ * - revisión de API Key
+ * - autorización por token JWT
+ * - verificación de permisos de usuario
+ *
+ * Permiso requerido: PERMISOS.ACTUALIZAR_SET_CUOTAS
+ *
+ * @module actualizarSetCuotas.routes
+ */
+
+
+
+const express = require('express');
+const controlador = require('@altertex/cuota/ctrl/actualizarSetCuotas.controller');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const RUTAS = require('@altertex/util/const/rutas');
+const PERMISOS = require('@altertex/util/const/permisos');
+
+const ruteador = express.Router();
+
+ruteador.put(
+ RUTAS.CUOTAS.ACTUALIZAR_SET_CUOTAS,
+ revisarApiKey(),
+ autorizarToken,
+ verificarPermisos(PERMISOS.ACTUALIZAR_SET_CUOTAS),
+ controlador.actualizarSetCuotas
+);
+
+module.exports = ruteador;
diff --git a/Cuotas/Rutas/RutasIndividuales/consultarCuotas.routes.js b/Cuotas/Rutas/RutasIndividuales/consultarCuotas.routes.js
new file mode 100644
index 00000000..11d420c4
--- /dev/null
+++ b/Cuotas/Rutas/RutasIndividuales/consultarCuotas.routes.js
@@ -0,0 +1,115 @@
+// Importación del framework Express para la creación de rutas HTTP.
+const express = require('express');
+
+// Creación de una instancia del enrutador de Express.
+const ruteador = express.Router();
+
+// Importación del controlador encargado de consultar la lista de sets de cuotas.
+const controlador = require('@altertex/cuota/ctrl/consultarListasCuotas.controller');
+
+// Importación de middlewares de seguridad para validar API Key, token JWT y permisos de usuario.
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+// Importación de constantes de permisos y rutas del sistema.
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * RF32 - Consulta Lista de Sets de Cuotas
+ * Documentación del requisito funcional:
+ * https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF32
+ */
+
+/**
+ * @swagger
+ * /api/cuotas/consultar-lista:
+ * post:
+ * summary: Consulta la lista de sets de cuotas del cliente autenticado.
+ * tags:
+ * - Cuotas
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * responses:
+ * 200:
+ * description: Consulta exitosa de sets de cuotas.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * message:
+ * type: string
+ * example: Consulta de cuotas exitosa.
+ * token:
+ * type: string
+ * example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
+ * 400:
+ * description: Error en la solicitud.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * message:
+ * type: string
+ * example: Error en la solicitud.
+ * 401:
+ * description: Credenciales inválidas o token no autorizado.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * message:
+ * type: string
+ * example: Credenciales inválidas, no tiene el permiso necesario.
+ * 403:
+ * description: No tiene el permiso necesario para realizar esta acción.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * message:
+ * type: string
+ * example: No tiene el permiso necesario.
+ * 404:
+ * description: No se encontraron sets de cuotas para el cliente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * message:
+ * type: string
+ * example: No se encontraron resultados.
+ * 500:
+ * description: Error interno al obtener los sets de cuotas.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * message:
+ * type: string
+ * example: Error al obtener los sets de cuotas.
+ */
+
+// Definición de la ruta POST para consultar la lista de sets de cuotas.
+// Protegida por validación de API Key, autenticación de token y verificación de permisos.
+ruteador.post(
+ RUTAS.CUOTAS.CONSULTAR_LISTA,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CONSULTAR_SETS_CUOTAS),
+ controlador.consultarLista,
+);
+
+// Exporta el enrutador para que pueda ser utilizado por la aplicación principal.
+module.exports = ruteador;
\ No newline at end of file
diff --git a/Cuotas/Rutas/RutasIndividuales/crearCuota.routes.js b/Cuotas/Rutas/RutasIndividuales/crearCuota.routes.js
new file mode 100644
index 00000000..d3565108
--- /dev/null
+++ b/Cuotas/Rutas/RutasIndividuales/crearCuota.routes.js
@@ -0,0 +1,109 @@
+const express = require("express");
+const ruteador = express.Router();
+const controlador = require("@altertex/cuota/ctrl/crearCuota.controller");
+
+const RUTAS = require("@altertex/util/const/rutas");
+const validarYSanitizar = require("@altertex/util/inter/validarYSanitizar");
+const revisarApiKey = require("@altertex/util/inter/revisarApiKey");
+const autorizarToken = require("@altertex/util/inter/autorizarToken");
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+/**
+ *
+ * RF31 - Crear Cuotas - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF31
+ *
+ * @swagger
+ * /api/cuotas/crear-cuota:
+ * post:
+ * summary: Crea un nuevo conjunto de cuotas (cuotaSet)
+ * tags:
+ * - Cuotas
+ * security:
+ * - ApiKeyAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * required:
+ * - idCliente
+ * - nombre
+ * - descripcion
+ * - periodoRenovacion
+ * - renovacionHabilitada
+ * - productosYLimite
+ * - ultimaActualizacion
+ * properties:
+ * idCliente:
+ * type: integer
+ * example: 102
+ * nombre:
+ * type: string
+ * example: "Cuota Abril"
+ * descripcion:
+ * type: string
+ * example: "Límites para el mes de abril"
+ * periodoRenovacion:
+ * type: string
+ * example: "mensual"
+ * renovacionHabilitada:
+ * type: boolean
+ * example: true
+ * ultimaActualizacion:
+ * type: string
+ * format: date
+ * example: "2025-04-19"
+ * productosYLimite:
+ * type: array
+ * items:
+ * type: object
+ * required:
+ * - idProducto
+ * - limite
+ * - limiteActual
+ * properties:
+ * idProducto:
+ * type: string
+ * example: "PROD001"
+ * limite:
+ * type: number
+ * example: 100
+ * limiteActual:
+ * type: number
+ * example: 0
+ * responses:
+ * 201:
+ * description: Cuota set creado exitosamente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * exito:
+ * type: string
+ * example: Cuota set creado exitosamente
+ * resultado:
+ * type: object
+ * 400:
+ * description: Error de validación o al crear el cuota set
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * error:
+ * type: string
+ * example: Error creando cuota set
+ */
+ruteador.post(
+ RUTAS.CUOTAS.AGREGAR,
+ validarYSanitizar,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ controlador.crearCuota
+);
+
+module.exports = ruteador;
diff --git a/Cuotas/Rutas/RutasIndividuales/eliminarSetCuotas.routes.js b/Cuotas/Rutas/RutasIndividuales/eliminarSetCuotas.routes.js
new file mode 100644
index 00000000..4cf89899
--- /dev/null
+++ b/Cuotas/Rutas/RutasIndividuales/eliminarSetCuotas.routes.js
@@ -0,0 +1,80 @@
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/cuota/ctrl/eliminarSetCuotas.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+/**
+ * RF35 - Elimina Set de Cuotas - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF35
+ */
+
+/**
+ * @swagger
+ * /api/cuotas/eliminar-set-cuotas:
+ * delete:
+ * summary: Elimina uno o varios sets de cuotas
+ * description: Este endpoint permite eliminar múltiples sets de cuotas dados sus IDs.
+ * tags: [Cuotas]
+ * security:
+ * - ApiKeyAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * idsSetCuotas:
+ * type: array
+ * description: IDs de los sets de cuotas a eliminar
+ * items:
+ * type: integer
+ * example: [1, 2, 3]
+ * responses:
+ * 200:
+ * description: Sets de cuotas eliminados correctamente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Sets de cuotas eliminados correctamente."
+ * 400:
+ * description: No se proporcionaron IDs válidos
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Set de cuota no encontrado."
+ * 500:
+ * description: Error en el servidor al intentar eliminar
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Error al eliminar set de cuotas."
+ */
+
+ruteador.post(
+ RUTAS.CUOTAS.ELIMINAR_SET_CUOTAS,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.ELIMINAR_SET_CUOTAS),
+ controlador.eliminarSetCuotas
+);
+
+module.exports = ruteador;
diff --git a/Cuotas/Rutas/RutasIndividuales/leerSetCuotas.routes.js b/Cuotas/Rutas/RutasIndividuales/leerSetCuotas.routes.js
new file mode 100644
index 00000000..e5481465
--- /dev/null
+++ b/Cuotas/Rutas/RutasIndividuales/leerSetCuotas.routes.js
@@ -0,0 +1,67 @@
+//RF33 - LEER COUTA SET - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF33]
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/cuota/ctrl/leerSetCuotas.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/cuotas/leer-set-cuotas:
+ * post:
+ * summary: Leer set de cuotas
+ * description: Obtiene el set de cuotas según los parámetros enviados.
+ * tags:
+ * - Cuotas
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * idSet:
+ * type: string
+ * description: ID del set de cuotas a consultar
+ * required:
+ * - idSet
+ * responses:
+ * '200':
+ * description: Set de cuotas obtenido correctamente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * cuotas:
+ * type: array
+ * items:
+ * type: object
+ * # Define los campos de cada cuota aquí
+ * '401':
+ * description: No autorizado (API Key o Token inválido)
+ * '403':
+ * description: Permisos insuficientes
+ * '400':
+ * description: Error de validación o parámetros incorrectos
+ * '500':
+ * description: Error interno del servidor
+ */
+
+ruteador.post(
+ RUTAS.CUOTAS.LEER_SET_CUOTAS,
+ validarYSanitizar,
+ revisarApiKey(),
+ autorizarToken,
+ verificarPermisos(PERMISOS.LEER_SET_CUOTAS),
+ controlador.leerSetCuotas
+);
+
+module.exports = ruteador;
diff --git a/Cuotas/Rutas/RutasIndividuales/obtenerOpcionesCuotas.routes.js b/Cuotas/Rutas/RutasIndividuales/obtenerOpcionesCuotas.routes.js
new file mode 100644
index 00000000..ead60383
--- /dev/null
+++ b/Cuotas/Rutas/RutasIndividuales/obtenerOpcionesCuotas.routes.js
@@ -0,0 +1,19 @@
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/cuota/ctrl/obtenerOpcionesCuotas.controller');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+const RUTAS = require('@altertex/util/const/rutas');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+
+ruteador.post(
+ RUTAS.CUOTAS.OPCIONES,
+ autorizarToken,
+ limitePeticionesDiarias,
+ revisarApiKey(),
+ controlador.obtenerOpcionesCuotas,
+);
+
+module.exports = ruteador;
diff --git a/Cuotas/Rutas/indexCuotas.routes.js b/Cuotas/Rutas/indexCuotas.routes.js
new file mode 100644
index 00000000..0c4056a8
--- /dev/null
+++ b/Cuotas/Rutas/indexCuotas.routes.js
@@ -0,0 +1,21 @@
+const express = require('express');
+const ruteador = express.Router();
+const rutaCrearCuota = require('@altertex/cuota/rutasInd/crearCuota.routes');
+const rutaObtenerOpcionesCuota = require('@altertex/cuota/rutasInd/obtenerOpcionesCuotas.routes');
+const rutasConsultarListaCuotas = require('@altertex/cuota/rutasInd/consultarCuotas.routes');
+const rutaEliminarSetCuotas = require('@altertex/cuota/rutasInd/eliminarSetCuotas.routes');
+const rutaLeerCuota = require('@altertex/cuota/rutasInd/leerSetCuotas.routes');
+const rutaActualizarSetCuotas = require('@altertex/cuota/rutasInd/actualizarSetCuotas.routes');
+
+
+const RUTAS = require('@altertex/util/const/rutas');
+
+ruteador.use(RUTAS.CUOTAS.BASE, rutaCrearCuota);
+ruteador.use(RUTAS.CUOTAS.BASE, rutaObtenerOpcionesCuota);
+ruteador.use(RUTAS.CUOTAS.BASE, rutasConsultarListaCuotas);
+ruteador.use(RUTAS.CUOTAS.BASE, rutaEliminarSetCuotas);
+ruteador.use(RUTAS.CUOTAS.BASE, rutaLeerCuota);
+ruteador.use(RUTAS.CUOTAS.BASE, rutaActualizarSetCuotas);
+
+
+module.exports = ruteador;
diff --git a/Empleados/Controladores/actualizarEmpleado.controller.js b/Empleados/Controladores/actualizarEmpleado.controller.js
new file mode 100644
index 00000000..ebd90016
--- /dev/null
+++ b/Empleados/Controladores/actualizarEmpleado.controller.js
@@ -0,0 +1,51 @@
+const MENSAJES = require('@altertex/util/const/mensajesEmpleados');
+const repositorio = require('@altertex/emp/repos/repositorioActualizarEmpleado');
+//RF[19] Actualizar empleado - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF19]
+
+/**
+ * Controlador para actualizar la información de un empleado.
+ *
+ * Este endpoint recibe un objeto con los cambios que se aplicarán
+ * sobre un empleado y usa su repositorio para hacer el cambio en la
+ * base de datos.
+ *
+ * @function actualizarEmpleado
+ * @async
+ * @param {Express.Request} req - Objeto de solicitud HTTP de Express.
+ * @param {object} req.body - Cuerpo de la solicitud.
+ * @param {object|Array} req.body.cambios - Información del empleado a actualizar.
+ * @param {Express.Response} res - Objecto de respuesta HTTP de Express.
+ * @returns {Promise} Retorna una respuesta JSON indicando éxito o un error.
+ */
+exports.actualizarEmpleado = async (req, res) => {
+ let datos;
+
+ // Si no hay cambios
+ if (req.body.id || req.body.idEmpleado) {
+ datos = [req.body];
+ } else if (req.body.cambios) {
+ // Si la información viene en el formato esperado (hay cambios)
+ datos = Array.isArray(req.body.cambios) ? req.body.cambios : [req.body.cambios];
+ } else {
+ return res
+ .status(MENSAJES.ERROR_ACTUALIZAR.codigo)
+ .json({ mensaje: MENSAJES.ERROR_ACTUALIZAR.mensaje });
+ }
+
+ if (!datos || datos.length === 0) {
+ return res
+ .status(MENSAJES.ERROR_ACTUALIZAR.codigo)
+ .json({ mensaje: MENSAJES.ERROR_ACTUALIZAR.mensaje });
+ }
+
+ try {
+ await repositorio.actualizarEmpleado(datos);
+ return res
+ .status(MENSAJES.EXITO_ACTUALIZAR.codigo)
+ .json({ mensaje: MENSAJES.EXITO_ACTUALIZAR.mensaje, datos });
+ } catch {
+ return res
+ .status(MENSAJES.ERROR_ACTUALIZAR.codigo)
+ .json({ mensaje: MENSAJES.ERROR_ACTUALIZAR.mensaje });
+ }
+};
diff --git a/Empleados/Controladores/actualizarGrupoEmpleado.controller.js b/Empleados/Controladores/actualizarGrupoEmpleado.controller.js
new file mode 100644
index 00000000..3687ffcc
--- /dev/null
+++ b/Empleados/Controladores/actualizarGrupoEmpleado.controller.js
@@ -0,0 +1,39 @@
+const MENSAJES = require('@altertex/util/const/mensajesGrupoEmpleados');
+const repositorio = require('@altertex/emp/repos/repositorioActualizarGrupo');
+
+// RF[24] Actualiza grupo empleado - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF24]
+
+/**
+ * Controlador HTTP para actualizar un grupo de empleados.
+ *
+ * Valida que el cuerpo de la solicitud contenga los datos necesarios,
+ * y delega la lógica de actualización al repositorio correspondiente.
+ *
+ * Respuestas posibles:
+ * - 400 si faltan datos en el cuerpo de la solicitud.
+ * - 200 si el grupo se actualiza correctamente.
+ * - 500 si ocurre un error en el proceso de actualización.
+ *
+ * @async
+ * @function actualizarGrupoEmpleados
+ * @param {Express.Request} req - Objeto de solicitud HTTP de Express.
+ * @param {Express.Response} res - Objeto de respuesta HTTP de Express.
+ * @returns {Promise} La respuesta HTTP con el estado y mensaje correspondiente.
+ */
+exports.actualizarGrupoEmpleados = async (req, res) => {
+ const datosActualizacion = req.body;
+ if (!datosActualizacion || Object.keys(datosActualizacion).length === 0) {
+ return res
+ .status(MENSAJES.FORMATO_INVALIDO_DATOS.codigo)
+ .json({ mensaje: MENSAJES.FORMATO_INVALIDO_DATOS.mensaje });
+ }
+ try {
+ await repositorio.actualizarGrupoEmpleados(datosActualizacion);
+
+ return res
+ .status(MENSAJES.GRUPO_ACTUALIZADO.codigo)
+ .json({ mensaje: MENSAJES.GRUPO_ACTUALIZADO.mensaje });
+ } catch (error) {
+ return res.status(MENSAJES.ERROR_ACTUALIZAR_GRUPOS.codigo).json({ mensaje: error.message });
+ }
+};
diff --git a/Empleados/Controladores/consultarLista.controller.js b/Empleados/Controladores/consultarLista.controller.js
new file mode 100644
index 00000000..ed3c7972
--- /dev/null
+++ b/Empleados/Controladores/consultarLista.controller.js
@@ -0,0 +1,45 @@
+const repositorio = require('@altertex/emp/repos/repositorioEmpleados');
+const MENSAJES_EMPLEADOS = require('@altertex/util/const/mensajesEmpleados');
+
+/**
+ * Controlador para la consulta de la lista de empleados de un cliente.
+ *
+ * RF17 - Consulta Lista de Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF17
+ *
+ * @async
+ * @function consultarLista
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.body - Cuerpo de la solicitud HTTP.
+ * @param {object} req.user - Datos del usuario autenticado.
+ * @param {number} req.user.clienteSeleccionado - ID del cliente seleccionado para la consulta.
+ * @param {object} res - Objeto de respuesta de Express.
+ *
+ * @returns {Response} Respuesta HTTP con estado:
+ * - 200 si la consulta es exitosa, junto con los datos de los empleados.
+ * - 400 si los parámetros proporcionados son inválidos.
+ * - 500 si ocurre un error en el servidor.
+ *
+ * @throws {Error} Si ocurre un error inesperado durante la operación.
+ */
+exports.consultarLista = async (req, res) => {
+ const idCliente = parseInt(req.user.clienteSeleccionado);
+
+ if (!idCliente) {
+ return res
+ .status(MENSAJES_EMPLEADOS.PARAMETROS_INVALIDOS.codigo)
+ .json({ mensaje: MENSAJES_EMPLEADOS.PARAMETROS_INVALIDOS.mensaje });
+ }
+
+ try {
+ const resultados = await repositorio.obtenerEmpleados(idCliente);
+
+ return res.status(MENSAJES_EMPLEADOS.CONSULTA_EXITOSA.codigo).json({
+ mensaje: MENSAJES_EMPLEADOS.CONSULTA_EXITOSA.mensaje,
+ empleados: resultados,
+ });
+ } catch {
+ return res.status(MENSAJES_EMPLEADOS.ERROR_CONSULTAR_EMPLEADOS.codigo).json({
+ mensaje: MENSAJES_EMPLEADOS.ERROR_CONSULTAR_EMPLEADOS.mensaje,
+ });
+ }
+};
diff --git a/Empleados/Controladores/consultarListaGrupos.controller.js b/Empleados/Controladores/consultarListaGrupos.controller.js
new file mode 100644
index 00000000..55e5a8c1
--- /dev/null
+++ b/Empleados/Controladores/consultarListaGrupos.controller.js
@@ -0,0 +1,45 @@
+const repositorio = require('@altertex/emp/repos/repositorioGrupoDeEmpleados');
+const MENSAJES_GRUPO_EMPLEADOS = require('@altertex/util/const/mensajesGrupoEmpleados');
+
+/**
+ * Controlador para la consulta de la lista de empleados de un cliente.
+ *
+ * RF22 - Consulta Lista de Grupo Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF22
+ *
+ * @async
+ * @function consultarLista
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.body - Cuerpo de la solicitud HTTP.
+ * @param {object} req.user - Datos del usuario autenticado.
+ * @param {number} req.user.clienteSeleccionado - ID del cliente seleccionado para la consulta.
+ * @param {object} res - Objeto de respuesta de Express.
+ *
+ * @returns {Response} Respuesta HTTP con estado:
+ * - 200 si la consulta es exitosa, junto con los datos de los empleados.
+ * - 400 si los parámetros proporcionados son inválidos.
+ * - 500 si ocurre un error en el servidor.
+ *
+ * @throws {Error} Si ocurre un error inesperado durante la operación.
+ */
+exports.consultarLista = async (req, res) => {
+ const idCliente = parseInt(req.user.clienteSeleccionado);
+
+ if (!idCliente) {
+ return res
+ .status(MENSAJES_GRUPO_EMPLEADOS.PARAMETROS_INVALIDOS.codigo)
+ .json({ mensaje: MENSAJES_GRUPO_EMPLEADOS.PARAMETROS_INVALIDOS.mensaje });
+ }
+
+ try {
+ const resultados = await repositorio.obtenerGrupoDeEmpleados(idCliente);
+
+ return res.status(MENSAJES_GRUPO_EMPLEADOS.CONSULTA_EXITOSA.codigo).json({
+ mensaje: MENSAJES_GRUPO_EMPLEADOS.CONSULTA_EXITOSA.mensaje,
+ grupoEmpleados: resultados,
+ });
+ } catch {
+ return res.status(MENSAJES_GRUPO_EMPLEADOS.ERROR_CONSULTAR_GRUPOS.codigo).json({
+ mensaje: MENSAJES_GRUPO_EMPLEADOS.ERROR_CONSULTAR_GRUPOS.mensaje,
+ });
+ }
+};
diff --git a/Empleados/Controladores/crearEmpleado.controller.js b/Empleados/Controladores/crearEmpleado.controller.js
new file mode 100644
index 00000000..4ecb4a14
--- /dev/null
+++ b/Empleados/Controladores/crearEmpleado.controller.js
@@ -0,0 +1,172 @@
+const bcrypt = require('bcryptjs');
+const repositorio = require('@altertex/emp/repos/repositorioCrearEmpleado');
+
+/**
+ * Controlador para crear un nuevo empleado.
+ * Este endpoint recibe un objeto con la información del nuevo empleado
+ * y usa su repositorio para insertar el nuevo registro en la base de datos.
+ *
+ * @function crearEmpleado
+ * @async
+ * @param {Array} req - Objeto de solicitud HTTP de Express.
+ * @param {Array} req.body - Cuerpo de la solicitud con los datos del nuevo empleado.
+ * @param {string} req.body[].nombreCompleto - Nombre completo del usuario.
+ * @param {string} req.body[].correoElectronico - Correo electrónico único del usuario.
+ * @param {string} req.body[].contrasenia - Contraseña en texto plano.
+ * @param {string} req.body[].numeroTelefono - Número de teléfono (10 dígitos).
+ * @param {string} req.body[].direccion - Dirección del usuario.
+ * @param {string} req.body[].fechaNacimiento - Fecha de nacimiento en formato YYYY-MM-DD.
+ * @param {string} req.body[].genero - Género del usuario.
+ * @param {boolean} req.body[].estatus - Estatus activo/inactivo del usuario.
+ * @param {number} req.body[].idRol - ID del rol asignado al usuario.
+ * @param {number|Array} req.body[].idCliente - ID(s) de cliente asociados.
+ * @param {string} req.body[].numeroEmergencia - Teléfono de emergencia del empleado.
+ * @param {string} req.body[].areaTrabajo - Área donde trabaja el empleado.
+ * @param {string} req.body[].posicion - Puesto del empleado.
+ * @param {number} req.body[].cantidadPuntos - Puntos iniciales del empleado.
+ * @param {string} req.body[].antiguedad - Fecha de ingreso (YYYY-MM-DD).
+ * @param {response} res - Objeto de respuesta HTTP.
+ * @returns {Promise}
+ *
+ * - 200 si el empleado se creó correctamente.
+ * - 400 si el cuerpo está vacío o no es un arreglo.
+ * - 500 si ocurre un error al crear el empleado.
+ */
+exports.crearEmpleado = async (req, res) => {
+ const {
+ nombreCompleto,
+ correoElectronico,
+ contrasenia,
+ numeroTelefono,
+ direccion,
+ fechaNacimiento,
+ genero,
+ estatus,
+ idRol,
+ idCliente,
+ numeroEmergencia,
+ areaTrabajo,
+ posicion,
+ cantidadPuntos,
+ antiguedad,
+ } = req.body;
+
+ // Validaciones críticas
+ if (!idCliente) {
+ return res.status(400).json({ mensaje: 'Cliente no seleccionado' });
+ }
+ if (
+ !nombreCompleto
+ || !correoElectronico
+ || !contrasenia
+ || !numeroTelefono
+ || !direccion
+ || !fechaNacimiento
+ || !genero
+ || estatus === undefined
+ || idRol === undefined
+ || !numeroEmergencia
+ || !areaTrabajo
+ || !posicion
+ || cantidadPuntos === undefined
+ || !antiguedad
+ ) {
+ return res.status(400).json({ mensaje: 'Faltan campos requeridos' });
+ }
+
+ // Validaciones de formato y longitud
+ if (nombreCompleto.length > 75) {
+ return res.status(400).json({ mensaje: 'El nombre es demasiado largo' });
+ }
+ if (!/^[A-Za-zÁÉÍÓÚáéíóúÑñ\s]+$/.test(nombreCompleto)) {
+ return res.status(400).json({ mensaje: 'El nombre solo puede contener letras y espacios' });
+ }
+ if (correoElectronico.length > 75) {
+ return res.status(400).json({ mensaje: 'El correo es demasiado largo' });
+ }
+ const correoValido = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ if (!correoValido.test(correoElectronico)) {
+ return res.status(400).json({ mensaje: 'El correo electrónico no es válido' });
+ }
+ if (contrasenia.length > 75) {
+ return res.status(400).json({ mensaje: 'La contraseña es demasiado larga' });
+ }
+ const tieneCaracterEspecial = /[!@#$%^&*(),.?":{}|<>]/;
+ const tieneMayuscula = /[A-Z]/;
+ if (
+ contrasenia.length < 8
+ || !tieneCaracterEspecial.test(contrasenia)
+ || !tieneMayuscula.test(contrasenia)
+ ) {
+ return res
+ .status(400)
+ .json({
+ mensaje:
+ 'La contraseña es débil. Debe tener al menos 8 caracteres, una mayúscula y un caracter especial.',
+ });
+ }
+ if (direccion.length > 150) {
+ return res.status(400).json({ mensaje: 'La dirección es demasiado larga' });
+ }
+ if (posicion.length > 75) {
+ return res.status(400).json({ mensaje: 'La posición es demasiado larga' });
+ }
+ if (areaTrabajo.length > 75) {
+ return res.status(400).json({ mensaje: 'El área de trabajo es demasiado larga' });
+ }
+ if (genero.length > 20) {
+ return res.status(400).json({ mensaje: 'El género es demasiado largo' });
+ }
+ if (isNaN(numeroEmergencia)) {
+ return res.status(400).json({ mensaje: 'El número de emergencia no es válido' });
+ }
+ if (!/^\d+$/.test(String(cantidadPuntos)) || Number(cantidadPuntos) < 0) {
+ return res
+ .status(400)
+ .json({ mensaje: 'Los puntos deben ser un número entero mayor o igual a 0' });
+ }
+ const telefonoValido = /^\d{10}$/;
+ if (!telefonoValido.test(numeroTelefono)) {
+ return res
+ .status(400)
+ .json({ mensaje: 'El número de teléfono debe tener 10 dígitos numéricos' });
+ }
+ const fechaRegex = /^\d{4}-\d{2}-\d{2}$/;
+ if (!fechaRegex.test(fechaNacimiento) || isNaN(Date.parse(fechaNacimiento))) {
+ return res
+ .status(400)
+ .json({ mensaje: 'La fecha de nacimiento no tiene un formato válido (YYYY-MM-DD)' });
+ }
+ if (!fechaRegex.test(antiguedad) || isNaN(Date.parse(antiguedad))) {
+ return res
+ .status(400)
+ .json({ mensaje: 'La antigüedad no tiene un formato válido (YYYY-MM-DD)' });
+ }
+
+ try {
+ const contraseniaEncriptada = await bcrypt.hash(contrasenia, 10);
+ const resultado = await repositorio.crearEmpleado({
+ nombreCompleto,
+ correoElectronico,
+ contrasenia: contraseniaEncriptada,
+ numeroTelefono,
+ direccion,
+ fechaNacimiento,
+ genero,
+ estatus,
+ idRol,
+ idCliente,
+ numeroEmergencia,
+ areaTrabajo,
+ posicion,
+ cantidadPuntos,
+ antiguedad,
+ });
+ return res.status(201).json({
+ mensaje: 'Empleado creado exitosamente',
+ datos: resultado,
+ });
+ } catch (error) {
+ return res.status(400).json({ mensaje: error.message });
+ }
+};
diff --git a/Empleados/Controladores/crearGrupoEmpleados.controller.js b/Empleados/Controladores/crearGrupoEmpleados.controller.js
new file mode 100644
index 00000000..13d2cb16
--- /dev/null
+++ b/Empleados/Controladores/crearGrupoEmpleados.controller.js
@@ -0,0 +1,68 @@
+//RF21 - Crear Grupo de Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF21
+/**
+ * @file crearGrupoEmpleados.controller.js
+ * @description
+ * Controlador encargado de crear un nuevo grupo de empleados y asignarles una lista de empleados.
+ */
+
+// Importación del repositorio con la lógica de negocio.
+const repositorio = require('@altertex/emp/repos/repositorioCrearGrupo');
+const MENSAJES = require('@altertex/util/const/mensajesEmpleados');
+
+/**
+ * Controlador para crear un grupo de empleados.
+ *
+ * @async
+ * @function crearGrupoEmpleados
+ * @param {object} req - Request HTTP
+ * @param {object} res - Response HTTP
+ * @returns {Promise}
+ */
+exports.crearGrupoEmpleados = async (req, res) => {
+ const {
+ nombreGrupo,
+ descripcion,
+ idCliente = parseInt(req.user.clienteSeleccionado),
+ listaEmpleados,
+ } = req.body;
+
+ // Validación de campos requeridos
+ if (
+ !nombreGrupo
+ || !descripcion
+ || !idCliente
+ || !Array.isArray(listaEmpleados)
+ || listaEmpleados.length === 0
+ ) {
+ return res.status(400).json({
+ mensaje: MENSAJES.DATOS_INCOMPLETOS.mensaje,
+ });
+ }
+
+ try {
+ // Validación de nombre duplicado
+ const yaExiste = await repositorio.existeGrupoConNombre(nombreGrupo.trim(), idCliente);
+ if (yaExiste) {
+ return res.status(400).json({
+ mensaje: MENSAJES.GRUPO_NOMBRE_REPETIDO.mensaje,
+ });
+ }
+
+ // Crear grupo y asignar empleados
+ const resultado = await repositorio.crearGrupoYAsignarEmpleados(
+ nombreGrupo,
+ descripcion,
+ idCliente,
+ listaEmpleados,
+ );
+
+ return res.status(201).json({
+ mensaje: MENSAJES.GRUPO_CREADO.mensaje,
+ idGrupo: resultado.idGrupo,
+ });
+ } catch {
+ return res.status(500).json({
+ mensaje: MENSAJES.ERROR_CREAR_GRUPO.mensaje,
+ });
+ }
+};
\ No newline at end of file
diff --git a/Empleados/Controladores/eliminarEmpleado.controller.js b/Empleados/Controladores/eliminarEmpleado.controller.js
new file mode 100644
index 00000000..7b03f7e6
--- /dev/null
+++ b/Empleados/Controladores/eliminarEmpleado.controller.js
@@ -0,0 +1,73 @@
+const repositorio = require('@altertex/emp/repos/repositorioEliminarEmpleado');
+const MENSAJES_EMPLEADOS = require('@altertex/util/const/mensajesEmpleados');
+
+/**
+ * Controlador para eliminar uno o varios empleados.
+ *
+ * RF[20] - Elimina empleado: https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF20
+ *
+ * Este controlador valida que se reciba un arreglo de IDs de empleados. Luego intenta eliminar
+ * cada uno de ellos mediante el repositorio correspondiente. Si alguno no existe o ya fue eliminado,
+ * se acumulan sus IDs. Si ocurre un error al eliminar, se registra el mensaje de error y se devuelve
+ * una respuesta HTTP adecuada.
+ *
+ * @async
+ * @function eliminarEmpleado
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.body - Cuerpo de la solicitud HTTP.
+ * @param {number[]} req.body.idsEmpleado - Array de IDs numéricos de los empleados a eliminar.
+ * @param {object} res - Objeto de respuesta de Express.
+ * @returns {Promise} Respuesta HTTP con:
+ * - `200 OK` si al menos un empleado fue eliminado exitosamente.
+ * - `404 Not Found` si todos los empleados estaban ausentes o ya eliminados.
+ * - `500 Internal Server Error` si ocurrió un error durante el proceso.
+ */
+exports.eliminarEmpleado = async (req, res) => {
+ const idsEmpleado = req.body.idsEmpleado;
+
+ // Validación de entrada
+ if (!Array.isArray(idsEmpleado) || idsEmpleado.length === 0) {
+ return res.status(MENSAJES_EMPLEADOS.EMPLEADO_NO_ENCONTRADO.codigo).json({
+ mensaje: MENSAJES_EMPLEADOS.EMPLEADO_NO_ENCONTRADO.mensaje,
+ });
+ }
+
+ const errores = [];
+ const noEncontrados = [];
+
+ // Intentar eliminar cada empleado individualmente
+ await Promise.all(
+ idsEmpleado.map(async (id) => {
+ try {
+ const resultado = await repositorio.eliminarEmpleado(id);
+ if (resultado.affectedRows === 0) {
+ noEncontrados.push(id);
+ }
+ } catch (err) {
+ errores.push({ id, error: err.message || 'Error desconocido' });
+ }
+ })
+ );
+
+ // Si hubo errores técnicos
+ if (errores.length > 0) {
+ return res.status(MENSAJES_EMPLEADOS.ERROR_ELIMINAR_EMPLEADO.codigo).json({
+ mensaje: MENSAJES_EMPLEADOS.ERROR_ELIMINAR_EMPLEADO.mensaje,
+ detalles: errores,
+ });
+ }
+
+ // Si ninguno de los empleados fue encontrado
+ if (noEncontrados.length === idsEmpleado.length) {
+ return res.status(MENSAJES_EMPLEADOS.EMPLEADO_NO_ENCONTRADO.codigo).json({
+ mensaje: 'Ninguno de los empleados fue encontrado o ya habían sido eliminados.',
+ ids: noEncontrados,
+ });
+ }
+
+ // Eliminación exitosa (parcial o total)
+ return res.status(MENSAJES_EMPLEADOS.EMPLEADO_ELIMINADO.codigo).json({
+ mensaje: MENSAJES_EMPLEADOS.EMPLEADO_ELIMINADO.mensaje,
+ noEncontrados: noEncontrados.length > 0 ? noEncontrados : undefined,
+ });
+};
diff --git a/Empleados/Controladores/eliminarGrupoEmpleados.controller.js b/Empleados/Controladores/eliminarGrupoEmpleados.controller.js
new file mode 100644
index 00000000..46345af0
--- /dev/null
+++ b/Empleados/Controladores/eliminarGrupoEmpleados.controller.js
@@ -0,0 +1,48 @@
+const repositorio = require('@altertex/emp/repos/repositorioEliminarGrupoEmpleados');
+const MENSAJES_EMPLEADOS = require('@altertex/util/const/mensajesGrupoEmpleados');
+
+/**
+ * RF25 - Eliminar Grupo de Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF25
+ * Controlador para eliminar uno o varios grupos de empleados.
+ *
+ * Este endpoint permite eliminar grupos de empleados especificados mediante sus IDs.
+ * El proceso elimina las relaciones entre empleados y grupos, y luego elimina los grupos en sí,
+ * utilizando una transacción para garantizar la integridad de la base de datos.
+ *
+ * @async
+ * @function eliminarGrupoEmpleados
+ * @param {object} req - Objeto de solicitud Express.
+ * @param {object} req.body - Cuerpo de la solicitud.
+ * @param {number[]} req.body.idsGrupo - Array de IDs de grupos de empleados a eliminar.
+ * @param {object} res - Objeto de respuesta Express.
+ * @returns {Promise} Respuesta HTTP con el resultado de la operación:
+ * - 200: Eliminación exitosa.
+ * - 400 o 500: Error al eliminar grupo(s) de empleados.
+ *
+ * @throws {Error} Error capturado si ocurre una falla durante el proceso de eliminación.
+ *
+ */
+exports.eliminarGrupoEmpleados = async (req, res) => {
+ try {
+ const idsGrupo = req.body.idsGrupo;
+
+ if (!Array.isArray(idsGrupo) || idsGrupo.length === 0) {
+ return res.status(MENSAJES_EMPLEADOS.ELIMINAR_GRUPO_ERROR.codigo).json({
+ mensaje: MENSAJES_EMPLEADOS.ELIMINAR_GRUPO_ERROR.mensaje,
+ });
+ }
+ await Promise.all(
+ idsGrupo.map(async (idGrupo) => {
+ await repositorio.eliminarGrupoConTransaccion(idGrupo);
+ })
+ );
+
+ return res.status(MENSAJES_EMPLEADOS.ELIMINAR_GRUPO_EXITOSO.codigo).json({
+ mensaje: MENSAJES_EMPLEADOS.ELIMINAR_GRUPO_EXITOSO.mensaje,
+ });
+ } catch {
+ return res.status(MENSAJES_EMPLEADOS.ELIMINAR_GRUPO_ERROR.codigo).json({
+ mensaje: MENSAJES_EMPLEADOS.ELIMINAR_GRUPO_ERROR.mensaje,
+ });
+ }
+};
diff --git a/Empleados/Controladores/exportarEmpleados.controller.js b/Empleados/Controladores/exportarEmpleados.controller.js
new file mode 100644
index 00000000..f3d3e4c3
--- /dev/null
+++ b/Empleados/Controladores/exportarEmpleados.controller.js
@@ -0,0 +1,73 @@
+const repositorio = require('@altertex/emp/repos/repositorioExportarEmpleado');
+const { Parser } = require('json2csv');
+const { format } = require('date-fns');
+const MENSAJES_EMPLEADOS = require('@altertex/util/const/mensajesEmpleados');
+
+/**
+ * Controlador para exportar empleados seleccionados de un cliente y retornar CSV como string en JSON.
+ *
+ * @async
+ * @function exportarEmpleados
+ * @param {Request} req
+ * @param {Response} res
+ * @returns {Response} JSON con mensaje + contenido CSV en texto plano
+ * @see [RF59 - Exportar Empleados](https://codeandco-wiki.netlify.app/docs/next/proyectos/textiles/documentacion/requisitos/RF59)
+ */
+exports.exportarEmpleados = async (req, res) => {
+ try {
+ const idCliente = parseInt(req.user.clienteSeleccionado);
+ const idsEmpleado = req.body.idsEmpleado;
+
+ if (!Array.isArray(idsEmpleado) || idsEmpleado.length === 0) {
+ return res.status(MENSAJES_EMPLEADOS.PARAMETROS_INVALIDOS.codigo).json({
+ mensaje: 'Debes seleccionar al menos un empleado para exportar.'
+ });
+ }
+
+ const idsSeleccionados = idsEmpleado.map(id => parseInt(id));
+ const empleados = await repositorio.obtenerEmpleadosExportacion(idCliente, idsSeleccionados);
+
+ if (!empleados || empleados.length === 0) {
+ return res.status(MENSAJES_EMPLEADOS.EMPLEADOS_NO_ENCONTRADOS.codigo).json({
+ mensaje: MENSAJES_EMPLEADOS.EMPLEADOS_NO_ENCONTRADOS.mensaje,
+ csv: ''
+ });
+ }
+
+ empleados.forEach(emp => {
+ emp.fechaNacimiento = format(new Date(emp.fechaNacimiento), 'dd/MM/yyyy');
+ emp.antiguedad = format(new Date(emp.antiguedad), 'dd/MM/yyyy');
+ });
+
+ const campos = [
+ { label: 'ID', value: 'idEmpleado' },
+ { label: 'Nombre completo', value: 'nombreCompleto' },
+ { label: 'Correo electrónico', value: 'correoElectronico' },
+ { label: 'Número de teléfono', value: 'numeroTelefono' },
+ { label: 'Dirección', value: 'direccion' },
+ { label: 'Fecha de nacimiento', value: 'fechaNacimiento' },
+ { label: 'Género', value: 'genero' },
+ { label: 'Estatus', value: 'estatus' },
+ { label: 'Número de emergencia', value: 'numeroEmergencia' },
+ { label: 'Área de trabajo', value: 'areaTrabajo' },
+ { label: 'Posición', value: 'posicion' },
+ { label: 'Cantidad de puntos', value: 'cantidadPuntos' },
+ { label: 'Antigüedad', value: 'antiguedad' }
+ ];
+
+ const parser = new Parser({ fields: campos });
+ const csv = parser.parse(empleados);
+ const csvConBOM = `\uFEFF${csv}`;
+
+ return res.status(MENSAJES_EMPLEADOS.LISTA_EMPLEADOS_EXPORTADA.codigo).json({
+ mensaje: MENSAJES_EMPLEADOS.LISTA_EMPLEADOS_EXPORTADA.mensaje,
+ csv: csvConBOM
+ });
+ } catch (error) {
+ console.error('Error al exportar empleados:', error);
+ return res.status(MENSAJES_EMPLEADOS.ERROR_EXPORTAR_EMPLEADOS.codigo).json({
+ mensaje: MENSAJES_EMPLEADOS.ERROR_EXPORTAR_EMPLEADOS.mensaje,
+ csv: ''
+ });
+ }
+};
\ No newline at end of file
diff --git a/Empleados/Controladores/importarEmpleados.controller.js b/Empleados/Controladores/importarEmpleados.controller.js
new file mode 100644
index 00000000..fde30429
--- /dev/null
+++ b/Empleados/Controladores/importarEmpleados.controller.js
@@ -0,0 +1,216 @@
+const bcrypt = require('bcryptjs');
+const repositorio = require('@altertex/emp/repos/repositorioImportarEmpleado');
+const MENSAJES_USUARIOS = require('@altertex/util/const/mensajesUsuarios');
+
+/**
+ * Controlador para importar múltiples empleados con su usuario asociado.
+ *
+ * Esta función valida y procesa un arreglo de objetos con la información completa
+ * de usuario y empleado. Aplica validaciones de formato, unicidad de correo,
+ * fortaleza de contraseña, y formato telefónico antes de delegar al repositorio.
+ *
+ * Cada objeto debe incluir los datos necesarios tanto para crear el usuario como
+ * para insertar al empleado en la base de datos.
+ *
+ * Si alguna fila falla, se continúa con las demás y se devuelve un resumen de errores.
+ *
+ * @async
+ * @function importarEmpleados
+ * @param {Array} req - Objeto de solicitud HTTP. Espera `req.body` como un arreglo de objetos empleados.
+ * @param {Array} req.body - Arreglo de objetos con datos de usuario y empleado.
+ * @param {string} req.body[].nombreCompleto - Nombre completo del usuario.
+ * @param {string} req.body[].correoElectronico - Correo electrónico único del usuario.
+ * @param {string} req.body[].contrasena - Contraseña en texto plano.
+ * @param {string} req.body[].numeroTelefono - Número de teléfono (10 dígitos).
+ * @param {string} req.body[].direccion - Dirección del usuario.
+ * @param {string} req.body[].fechaNacimiento - Fecha de nacimiento en formato YYYY-MM-DD.
+ * @param {string} req.body[].genero - Género del usuario.
+ * @param {boolean} req.body[].estatus - Estatus activo/inactivo del usuario.
+ * @param {number} req.body[].idRol - ID del rol asignado al usuario.
+ * @param {number|Array} req.body[].idCliente - ID(s) de cliente asociados.
+ * @param {string} req.body[].numeroEmergencia - Teléfono de emergencia del empleado.
+ * @param {string} req.body[].areaTrabajo - Área donde trabaja el empleado.
+ * @param {string} req.body[].posicion - Puesto del empleado.
+ * @param {number} req.body[].cantidadPuntos - Puntos iniciales del empleado.
+ * @param {string} req.body[].antiguedad - Fecha de ingreso (YYYY-MM-DD).
+ * @param {response} res - Objeto de respuesta HTTP.
+ * @returns {Promise}
+ * - 200 si todos los empleados se importaron correctamente.
+ * - 207 si hubo errores parciales en una o más filas (respuesta incluye `errores`).
+ * - 400 si el cuerpo está vacío o no es un arreglo.
+ *
+ */
+exports.importarEmpleados = async (req, res) => {
+ const idCliente = parseInt(req.user.clienteSeleccionado);
+ const empleados = req.body;
+
+ if (!Array.isArray(empleados) || empleados.length === 0) {
+ return res.status(400).json({ mensaje: 'No se recibieron empleados.' });
+ }
+
+ const errores = [];
+ const listaParaImportar = [];
+
+ for (const [index, datos] of empleados.entries()) {
+ const fila = `Fila ${index + 1}`;
+ const {
+ nombreCompleto,
+ correoElectronico,
+ contrasena,
+ numeroTelefono
+ } = datos;
+
+ if (
+ !numeroTelefono
+ || !datos.direccion
+ || !datos.fechaNacimiento
+ || !datos.genero
+ || !datos.numeroEmergencia
+ || !datos.areaTrabajo
+ || !datos.posicion
+ || !datos.antiguedad
+ ) {
+ errores.push({ fila, error: 'Faltan campos requeridos' });
+ continue;
+ }
+
+ if (!nombreCompleto){
+ errores.push({ fila, error: 'El nombre es requerido' });
+ continue;
+ } if (nombreCompleto.length > 75) {
+ errores.push({ fila, error: 'El nombre es demasiado largo' });
+ continue;
+ } if (!/^[A-Za-zÁÉÍÓÚáéíóúÑñ\s]+$/.test(nombreCompleto)) {
+ errores.push({ fila, error: 'El nombre solo puede contener letras y espacios' });
+ continue;
+ }
+
+ if (!correoElectronico) {
+ errores.push({ fila, error: 'El correo es requerido' });
+ continue;
+ } if (correoElectronico && correoElectronico.length > 75) {
+ errores.push({ fila, error: 'El correo es demasiado largo' });
+ continue;
+ }
+
+ if (!contrasena) {
+ errores.push({ fila, error: 'La contraseña es requerida' });
+ continue;
+ } if (contrasena.length > 75) {
+ errores.push({ fila, error: 'La contraseña es demasiado larga' });
+ continue;
+ }
+
+ if (typeof datos.idCliente !== 'undefined' && datos.idCliente !== '' && datos.idCliente !== null) {
+ errores.push({ fila, error: 'El cliente no debe ser incluido en el archivo' });
+ continue;
+ }
+
+ if (datos.direccion.length > 150) {
+ errores.push({ fila, error: 'La dirección es demasiado larga' });
+ continue;
+ }
+
+ if (datos.estatus == null) {
+ errores.push({ fila, error: 'Estatus inválido: debe ser 0 o 1' });
+ continue;
+ }
+
+ if (datos.posicion.length > 75) {
+ errores.push({ fila, error: 'La posición es demasiado larga' });
+ continue;
+ }
+
+ if(datos.areaTrabajo.length > 75) {
+ errores.push({ fila, error: 'El área de trabajo es demasiado larga' });
+ continue;
+ }
+
+ if (datos.genero.length > 20) {
+ errores.push({ fila, error: 'El género es demasiado largo' });
+ continue;
+ }
+
+ if (isNaN(datos.numeroEmergencia)) {
+ errores.push({ fila, error: 'El número de emergencia no es valido' });
+ continue;
+ }
+
+ if (
+ !/^\d+$/.test(String(datos.cantidadPuntos))
+ || Number(datos.cantidadPuntos) < 0) {
+ errores.push({ fila, error: 'Los puntos deben ser un número entero mayor o igual a 0' });
+ continue;
+ }
+
+ // Correo válido
+ const correoValido = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ if (!correoValido.test(correoElectronico)) {
+ errores.push({ fila, error: MENSAJES_USUARIOS.CORREO_INVALIDO.mensaje });
+ continue;
+ }
+
+ // Contraseña fuerte
+ const tieneCaracterEspecial = /[!@#$%^&*(),.?":{}|<>]/;
+ const tieneMayuscula = /[A-Z]/;
+ if (
+ contrasena.length < 8
+ || !tieneCaracterEspecial.test(contrasena)
+ || !tieneMayuscula.test(contrasena)
+ ) {
+ errores.push({ fila, error: MENSAJES_USUARIOS.CONTRASENA_DEBIL.mensaje });
+ continue;
+ }
+
+ // Teléfono válido
+ const telefonoValido = /^\d{10}$/;
+ if (!telefonoValido.test(numeroTelefono)) {
+ errores.push({ fila, error: MENSAJES_USUARIOS.TELEFONO_INVALIDO.mensaje });
+ continue;
+ }
+
+ const fechaRegex = /^\d{4}-\d{2}-\d{2}$/;
+ if (!fechaRegex.test(datos.fechaNacimiento) || isNaN(Date.parse(datos.fechaNacimiento))) {
+ errores.push({ fila, error: 'La fecha de nacimiento no tiene un formato válido (DD-MM-YYYY)' });
+ continue;
+ }
+ if (!fechaRegex.test(datos.antiguedad) || isNaN(Date.parse(datos.antiguedad))) {
+ errores.push({ fila, error: 'La antigüedad no tiene un formato válido (DD-MM-YYYY)' });
+ continue;
+ }
+
+ try {
+ const hash = await bcrypt.hash(contrasena, 10);
+ listaParaImportar.push({
+ ...datos,
+ contrasena: hash
+ });
+ } catch (err) {
+ errores.push({ fila, error: `Error al procesar contraseña: ${err.message}` });
+ }
+ }
+
+ if (errores.length > 0) {
+ return res.status(207).json({
+ mensaje: 'Importación parcial con errores.',
+ errores
+ });
+ }
+
+ for (const empleado of listaParaImportar) {
+ empleado.idCliente = idCliente;
+ }
+
+ try {
+ await repositorio.importarEmpleadosMasivo(listaParaImportar);
+ } catch (error) {
+ errores.push({
+ fila: "",
+ error: error.message
+ });
+ }
+
+ return res.status(200).json({
+ mensaje: 'Todos los empleados importados correctamente.'
+ });
+};
diff --git a/Empleados/Controladores/leerGrupoEmpleados.controller.js b/Empleados/Controladores/leerGrupoEmpleados.controller.js
new file mode 100644
index 00000000..b9f85ee9
--- /dev/null
+++ b/Empleados/Controladores/leerGrupoEmpleados.controller.js
@@ -0,0 +1,42 @@
+const repositorio = require('@altertex/emp/repos/repositorioLeerGrupoDeEmpleados');
+const MENSAJES_GRUPO_EMPLEADOS = require('@altertex/util/const/mensajesGrupoEmpleados');
+
+/**
+ * Lee los detalles de un grupo de empleados desde la base de datos utilizando su ID.
+ *
+ * Valida el parámetro `idGrupo` y obtiene la información del grupo de empleados a través del repositorio.
+ * Si el grupo de empleados no es encontrado o el parámetro es inválido, retorna un error.
+ *
+ * @param {Express.Request} req - La solicitud HTTP que contiene el `idGrupo` en el cuerpo.
+ * @param {Express.Response} res - La respuesta HTTP para enviar el resultado al cliente.
+ * @returns {Promise} Responde con el grupo de empleados encontrado o un mensaje de error.
+ *
+ * @see RF[23] Lee grupo de empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF23
+ */
+exports.leerGrupoEmpleados = async (req, res) => {
+ const idGrupo = parseInt(req.body.idGrupo);
+
+ if (isNaN(idGrupo)) {
+ return res
+ .status(MENSAJES_GRUPO_EMPLEADOS.PARAMETROS_INVALIDOS.codigo)
+ .json({ mensaje: MENSAJES_GRUPO_EMPLEADOS.PARAMETROS_INVALIDOS.mensaje });
+ }
+ try {
+ const grupoEmpleados = await repositorio.obtenerGrupoEmpleadosPorId(idGrupo);
+
+ if (!grupoEmpleados) {
+ return res
+ .status(MENSAJES_GRUPO_EMPLEADOS.GRUPO_NO_ENCONTRADO.codigo)
+ .json({ mensaje: MENSAJES_GRUPO_EMPLEADOS.GRUPO_NO_ENCONTRADO.mensaje });
+ }
+
+ return res.status(MENSAJES_GRUPO_EMPLEADOS.GRUPO_OBTENIDO.codigo).json({
+ mensaje: MENSAJES_GRUPO_EMPLEADOS.GRUPO_OBTENIDO.mensaje,
+ grupoEmpleados,
+ });
+ } catch {
+ return res
+ .status(MENSAJES_GRUPO_EMPLEADOS.ERROR_OBTENER_GRUPO.codigo)
+ .json({ mensaje: MENSAJES_GRUPO_EMPLEADOS.ERROR_OBTENER_GRUPO.mensaje });
+ }
+};
diff --git a/Empleados/Datos/Repositorios/repositorioActualizarEmpleado.js b/Empleados/Datos/Repositorios/repositorioActualizarEmpleado.js
new file mode 100644
index 00000000..eca4d541
--- /dev/null
+++ b/Empleados/Datos/Repositorios/repositorioActualizarEmpleado.js
@@ -0,0 +1,47 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const MENSAJES = require('@altertex/util/const/mensajesEmpleados');
+const CONSULTAS_EMPLEADOS = require('@altertex/util/const/consultasEmpleados');
+
+//RF[19] Actualizar empleado - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF19]
+
+/**
+ *Repositorio para actualizar los datos de un empleado en la BD.
+ *
+ * Recorre un arreglo de objetos que contienen la información de cada empleado para
+ * actualizar su información.
+ *
+ * Utiliza un array de objetos con la información del empleado, y hace la
+ * consulta correspondiente a la base de datos.
+ *
+ * @function actualizarEmpleado
+ * @async
+ * @param {Array<{ idEmpleado: number, idUsuario: number, numeroEmergencia:
+ * number, areaTrabajo: string, posicion: string,
+ * cantidadPuntos: number, antiguedad: Date}>} datos - Lista de
+ * información del empleado a actualizar.
+ * @throws {Error} Si el arreglo está vacío o si ocurre un error en la base de datos.
+ * @returns {Promise} Promesa que se resuelve cuando todas las actualizaciones han sido ejecutadas.
+ */
+exports.actualizarEmpleado = async (datos) => {
+ if (!Array.isArray(datos) || datos.length === 0) {
+ throw new Error('Sin datos para actualizar.');
+ }
+ try {
+ await Promise.all(
+ datos.map(
+ ({ idEmpleado, numeroEmergencia, areaTrabajo, posicion, cantidadPuntos, antiguedad }) => {
+ return correrQuery(CONSULTAS_EMPLEADOS.ACTUALIZAR, [
+ numeroEmergencia,
+ areaTrabajo,
+ posicion,
+ cantidadPuntos,
+ antiguedad,
+ idEmpleado,
+ ]);
+ }
+ )
+ );
+ } catch {
+ throw new Error(MENSAJES.ERROR_ACTUALIZAR.mensaje);
+ }
+};
diff --git a/Empleados/Datos/Repositorios/repositorioActualizarGrupo.js b/Empleados/Datos/Repositorios/repositorioActualizarGrupo.js
new file mode 100644
index 00000000..4f803667
--- /dev/null
+++ b/Empleados/Datos/Repositorios/repositorioActualizarGrupo.js
@@ -0,0 +1,111 @@
+const CONSULTAS = require('@altertex/util/const/consultasGrupoEmpleados');
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const MENSAJES = require('@altertex/util/const/mensajesGrupoEmpleados');
+// RF[24] Actualiza grupo empleado - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF24]
+
+/**
+ * Actualiza un grupo de empleados en la base de datos, incluyendo su nombre,
+ * descripción, empleados asociados y sets de productos relacionados.
+ *
+ * Esta función realiza:
+ * - La actualización del nombre y descripción del grupo.
+ * - La verificación y reemplazo de los empleados asociados al grupo.
+ * - La verificación y reemplazo de los sets de productos asociados al grupo.
+ *
+ * En caso de que los empleados o sets proporcionados no pertenezcan al mismo cliente,
+ * se lanza un error.
+ *
+ * Nota: Si empleados o setsDeProductos están vacíos, se eliminan todas las asociaciones existentes.
+ *
+ * @async
+ * @function actualizarGrupoEmpleados
+ * @param {object} datosActualizacion - Datos necesarios para actualizar el grupo.
+ * @param {number} datosActualizacion.idGrupoEmpleado - ID del grupo de empleados a actualizar.
+ * @param {string} datosActualizacion.nombre - Nuevo nombre del grupo.
+ * @param {string} datosActualizacion.descripcion - Nueva descripción del grupo.
+ * @param {number[]} datosActualizacion.empleados - Lista de IDs de empleados a asociar al grupo. Array vacío elimina todas las asociaciones.
+ * @param {number[]} datosActualizacion.setsDeProductos - Lista de IDs de sets de productos a asociar al grupo. Array vacío elimina todas las asociaciones.
+ * @throws {Error} Si ocurre algún error durante la actualización o verificación de empleados/sets.
+ */
+exports.actualizarGrupoEmpleados = async (datosActualizacion) => {
+ const { idGrupoEmpleado, nombre, descripcion, empleados, setsDeProductos } = datosActualizacion;
+
+ try {
+ // Actualizar nombre y descripción del grupo
+ await correrQuery(CONSULTAS.ACTUALIZAR_GRUPO_EMPLEADOS_NOMBRE_DESCRIPCION, [
+ nombre,
+ descripcion,
+ idGrupoEmpleado,
+ nombre,
+ descripcion,
+ ]);
+
+ // Manejar empleados (incluyendo arrays vacíos)
+ if (empleados !== undefined && Array.isArray(empleados)) {
+ if (empleados.length > 0) {
+ // Si hay empleados, verificar que pertenezcan al mismo cliente
+ const empleadosSTR = empleados.join(', ');
+ const valores = empleados
+ .map((empleadoId) => `(${empleadoId}, ${idGrupoEmpleado})`)
+ .join(', ');
+
+ const resultadoVerificacion = await correrQuery(
+ CONSULTAS.VERIFICAR_EMPLEADOS_CLIENTE.replace('__EMPLEADOS__', empleadosSTR),
+ [idGrupoEmpleado],
+ );
+
+ if (resultadoVerificacion[0].validos !== empleados.length) {
+ throw new Error(MENSAJES.ERROR_VERIFICACION_CLIENTE_EMPLEADO.mensaje);
+ }
+
+ // Eliminar empleados que no están en la nueva lista
+ await correrQuery(
+ CONSULTAS.ELIMINAR_EMPLEADOS_DE_GRUPO_BASE.replace('__ID__', idGrupoEmpleado).replace(
+ '__EMPLEADOS__',
+ empleadosSTR,
+ ),
+ );
+
+ // Agregar los nuevos empleados
+ await correrQuery(CONSULTAS.AGREGAR_EMPLEADOS_NUEVOS_BASE.replace('__VALORES__', valores));
+ } else {
+ // Si el array está vacío, eliminar todas las asociaciones de empleados
+ await correrQuery(CONSULTAS.ELIMINAR_TODOS_EMPLEADOS_DE_GRUPO, [idGrupoEmpleado]);
+ }
+ }
+
+ // Manejar sets de productos (incluyendo arrays vacíos)
+ if (setsDeProductos !== undefined && Array.isArray(setsDeProductos)) {
+ if (setsDeProductos.length > 0) {
+ // Si hay sets, verificar que pertenezcan al mismo cliente
+ const setsSTR = setsDeProductos.join(', ');
+ const valores = setsDeProductos.map((setId) => `(${setId}, ${idGrupoEmpleado})`).join(', ');
+
+ const resultadoVerificacion = await correrQuery(
+ CONSULTAS.VERIFICAR_SETS_CLIENTE.replace('__SETS__', setsSTR),
+ [idGrupoEmpleado],
+ );
+
+ if (resultadoVerificacion[0].validos !== setsDeProductos.length) {
+ throw new Error(MENSAJES.ERROR_VERIFICACION_CLIENTE_SET.mensaje);
+ }
+
+ // Eliminar sets que no están en la nueva lista
+ await correrQuery(
+ CONSULTAS.ELIMINAR_SETS_DE_GRUPO_BASE.replace('__ID__', idGrupoEmpleado).replace(
+ '__SETS__',
+ setsSTR,
+ ),
+ );
+
+ // Agregar los nuevos sets
+ await correrQuery(CONSULTAS.AGREGAR_SETS_NUEVOS_BASE.replace('__VALORES__', valores));
+ } else {
+ // Si el array está vacío, eliminar todas las asociaciones de sets
+ await correrQuery(CONSULTAS.ELIMINAR_TODOS_SETS_DE_GRUPO, [idGrupoEmpleado]);
+ }
+ }
+ } catch (error) {
+ throw new Error(error);
+ }
+};
\ No newline at end of file
diff --git a/Empleados/Datos/Repositorios/repositorioCrearEmpleado.js b/Empleados/Datos/Repositorios/repositorioCrearEmpleado.js
new file mode 100644
index 00000000..ed0ed8f2
--- /dev/null
+++ b/Empleados/Datos/Repositorios/repositorioCrearEmpleado.js
@@ -0,0 +1,156 @@
+const db = require('@altertex/util/bd/db');
+const ROL_PREDETERMINADO = 3; // ID del rol por defecto para empleados
+
+const CONSULTAS_EMPLEADOS = require('@altertex/util/const/consultasEmpleados');
+const CONSULTAS_IMPORTAR_EMPLEADOS = require('@altertex/util/const/consultasImportarEmpleados');
+
+//RF[16] Crear empleado - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF16]
+
+/**
+ * Crea un nuevo empleado y su usuario asociado en la base de datos.
+ *
+ * @async
+ * @function crearEmpleado
+ * @param {object} empleado - Objeto con los datos del nuevo empleado.
+ * @param {string} empleado.nombreCompleto - Nombre completo del usuario.
+ * @param {string} empleado.correoElectronico - Correo electrónico único del usuario.
+ * @param {string} empleado.contrasena - Contraseña en texto plano (ya hasheada).
+ * @param {string} empleado.numeroTelefono - Teléfono del usuario (exactamente 10 dígitos).
+ * @param {string} empleado.direccion - Dirección del usuario.
+ * @param {string} empleado.fechaNacimiento - Fecha de nacimiento (YYYY-MM-DD).
+ * @param {string} empleado.genero - Género del usuario.
+ * @param {boolean} empleado.estatus - Estatus del usuario (true = activo, false = inactivo).
+ * @param {number} empleado.idRol - ID del rol asignado al usuario.
+ * @param {number} empleado.idCliente - ID del cliente asociado al usuario.
+ * @param {string} empleado.numeroEmergencia - Teléfono de emergencia del empleado.
+ * @param {string} empleado.areaTrabajo - Área de trabajo del empleado.
+ * @param {string} empleado.posicion - Puesto o cargo del empleado.
+ * @param {number} empleado.cantidadPuntos - Puntos acumulados del empleado.
+ * @param {string} empleado.antiguedad - Fecha de antigüedad/ingreso (YYYY-MM-DD).
+ * @throws {Error} Si el parámetro "empleado" no es un objeto válido o está vacío.
+ * @throws {Error} Si ocurre cualquier fallo durante la inserción en la transacción.
+ *
+ * @returns {Promise} Resuelve con un objeto que contiene el ID del nuevo empleado y su usuario.
+ */
+exports.crearEmpleado = async (empleado) => {
+ if (!empleado || typeof empleado !== 'object') {
+ throw new Error('No se recibió un empleado válido para importar.');
+ }
+
+ const conn = await db.getConnection();
+
+ try {
+ await conn.beginTransaction();
+
+ // Validar correo duplicado
+ const [correoExistente] = await conn.query(
+ CONSULTAS_IMPORTAR_EMPLEADOS.VALIDAR_CORREOS_DUPLICADOS,
+ [[empleado.correoElectronico]]
+ );
+ if (correoExistente.length > 0) {
+ throw new Error(`Correo ya registrado: ${empleado.correoElectronico}`);
+ }
+
+ // Validar fecha de nacimiento
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(empleado.fechaNacimiento)) {
+ throw new Error('Fecha de nacimiento inválida. Debe ser en formato YYYY-MM-DD.');
+ }
+ const fechaNacimiento = new Date(empleado.fechaNacimiento);
+ if (isNaN(fechaNacimiento.getTime())) {
+ throw new Error('Fecha de nacimiento inválida.');
+ }
+ const hoy = new Date();
+ if (fechaNacimiento > hoy) {
+ throw new Error('La fecha de nacimiento no puede ser futura.');
+ }
+ if (fechaNacimiento.getFullYear() < 1900) {
+ throw new Error('La fecha de nacimiento no puede ser anterior a 1900.');
+ }
+
+ // Validar que sea mayor o igual a 18 años
+ const edad = hoy.getFullYear() - fechaNacimiento.getFullYear();
+ const mes = hoy.getMonth() - fechaNacimiento.getMonth();
+ const dia = hoy.getDate() - fechaNacimiento.getDate();
+ let edadFinal = edad;
+ if (mes < 0 || (mes === 0 && dia < 0)) {
+ edadFinal -= 1;
+ }
+ if (edadFinal < 18) {
+ throw new Error('El empleado debe tener al menos 18 años.');
+ }
+
+ // Validar teléfono duplicado
+ const [telefonoExistente] = await conn.query(
+ CONSULTAS_IMPORTAR_EMPLEADOS.VALIDAR_TELEFONO_DUPLICADO,
+ [[empleado.numeroTelefono]]
+ );
+ if (telefonoExistente.length > 0) {
+ throw new Error(`Teléfono ya registrado: ${empleado.numeroTelefono}`);
+ }
+
+ //Validar antigüedad
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(empleado.antiguedad)) {
+ throw new Error('Antigüedad inválida. Debe ser en formato YYYY-MM-DD.');
+ }
+ const fechaAntiguedad = new Date(empleado.antiguedad);
+ if (isNaN(fechaAntiguedad.getTime())) {
+ throw new Error('Antigüedad inválida.');
+ }
+ if (fechaAntiguedad > hoy) {
+ throw new Error('La antigüedad no puede ser futura.');
+ }
+ if (fechaAntiguedad.getFullYear() < 1900) {
+ throw new Error('La antigüedad no puede ser anterior a 1900.');
+ }
+ // Validar que la antigüedad sea menor o igual a la fecha de nacimiento
+ if (fechaAntiguedad < fechaNacimiento) {
+ throw new Error('La antigüedad no puede ser anterior a la fecha de nacimiento.');
+ }
+ // Validar que la antigüedad sea menor o igual a la fecha actual
+ if (fechaAntiguedad > hoy) {
+ throw new Error('La antigüedad no puede ser posterior a la fecha actual.');
+ }
+
+ // Insertar usuario
+ const [resultadoUsuario] = await conn.query(CONSULTAS_EMPLEADOS.INSERTAR_USUARIO, [
+ empleado.nombreCompleto,
+ empleado.correoElectronico,
+ empleado.contrasenia,
+ empleado.numeroTelefono,
+ empleado.direccion,
+ empleado.fechaNacimiento,
+ empleado.genero,
+ empleado.estatus,
+ ]);
+ const idUsuario = resultadoUsuario.insertId;
+
+ // Insertar rol
+ await conn.query(CONSULTAS_EMPLEADOS.INSERTAR_ROL, [idUsuario, ROL_PREDETERMINADO]);
+
+ // Insertar asociación usuario-cliente
+ const listaClientes = Array.isArray(empleado.idCliente)
+ ? empleado.idCliente
+ : [empleado.idCliente];
+ for (const idCli of listaClientes) {
+ await conn.query(CONSULTAS_EMPLEADOS.INSERTAR_USUARIO_CLIENTE, [idUsuario, idCli]);
+ }
+
+ // Insertar empleado
+ await conn.query(CONSULTAS_EMPLEADOS.INSERTAR_EMPLEADO, [
+ idUsuario,
+ empleado.idCliente,
+ empleado.numeroEmergencia,
+ empleado.areaTrabajo,
+ empleado.posicion,
+ parseFloat(empleado.cantidadPuntos),
+ empleado.antiguedad,
+ ]);
+
+ await conn.commit();
+ } catch (err) {
+ await conn.rollback();
+ throw new Error(`${err.message}`);
+ } finally {
+ if (conn) conn.release();
+ }
+};
diff --git a/Empleados/Datos/Repositorios/repositorioCrearGrupo.js b/Empleados/Datos/Repositorios/repositorioCrearGrupo.js
new file mode 100644
index 00000000..e2d3e9a9
--- /dev/null
+++ b/Empleados/Datos/Repositorios/repositorioCrearGrupo.js
@@ -0,0 +1,73 @@
+// RF21 - Crear Grupo de Empleados
+const db = require('@altertex/util/bd/db');
+const CONSULTAS = require('@altertex/util/const/consultasGrupoEmpleados');
+
+/**
+ * Crea un nuevo grupo de empleados y asigna una lista de empleados al grupo.
+ *
+ * @async
+ * @function crearGrupoYAsignarEmpleados
+ * @param {string} nombreGrupo - Nombre del nuevo grupo.
+ * @param {string} descripcion - Descripción del grupo.
+ * @param {number} idCliente - ID del cliente al que pertenece el grupo.
+ * @param {number[]} listaEmpleados - Lista de IDs de empleados que se asignarán al grupo.
+ * @returns {Promise<{idGrupo: number}>} El ID del grupo creado.
+ * @throws {Error} Si ocurre un error durante la transacción.
+ */
+exports.crearGrupoYAsignarEmpleados = async (nombreGrupo, descripcion, idCliente, listaEmpleados) => {
+ const conexion = await db.getConnection();
+
+ try {
+ await conexion.beginTransaction();
+
+ // Inserta el grupo en la base de datos
+ const [resultadoGrupo] = await conexion.query(
+ CONSULTAS.CREAR_GRUPO,
+ [idCliente, nombreGrupo, descripcion]
+ );
+
+ const idGrupo = resultadoGrupo.insertId;
+
+ // Asigna los empleados al grupo
+ for (const idEmpleado of listaEmpleados) {
+ await conexion.query(
+ CONSULTAS.ASIGNAR_EMPLEADO_A_GRUPO,
+ [idEmpleado, idGrupo]
+ );
+ }
+
+ await conexion.commit();
+ return { idGrupo };
+ } catch (error) {
+ await conexion.rollback();
+ throw error;
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
+
+/**
+ * Verifica si ya existe un grupo con el mismo nombre para un cliente dado.
+ *
+ * @async
+ * @function existeGrupoConNombre
+ * @param {string} nombreGrupo - Nombre del grupo a validar.
+ * @param {number} idCliente - ID del cliente.
+ * @returns {Promise} `true` si el grupo ya existe, `false` si no.
+ * @throws {Error} Si ocurre un error durante la consulta.
+ */
+exports.existeGrupoConNombre = async (nombreGrupo, idCliente) => {
+ const conexion = await db.getConnection();
+
+ try {
+ const [resultados] = await conexion.query(
+ CONSULTAS.VALIDAR_NOMBRE_REPETIDO,
+ [idCliente, nombreGrupo.trim()]
+ );
+ return resultados.length > 0;
+ } catch {
+ throw new Error("Ya existe un grupo con ese nombre");
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
diff --git a/Empleados/Datos/Repositorios/repositorioEliminarEmpleado.js b/Empleados/Datos/Repositorios/repositorioEliminarEmpleado.js
new file mode 100644
index 00000000..204860eb
--- /dev/null
+++ b/Empleados/Datos/Repositorios/repositorioEliminarEmpleado.js
@@ -0,0 +1,33 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_EMPLEADOS = require('@altertex/util/const/consultasEmpleados');
+
+/**
+ * Elimina un empleado y su usuario vinculado.
+ *
+ * @param {number} idEmpleado - ID del empleado a eliminar.
+ * @returns {Promise<{affectedRows: number}>} Resultado de la eliminación del empleado.
+ */
+exports.eliminarEmpleado = async (idEmpleado) => {
+ try {
+ // 1. Obtener el idUsuario asociado al empleado
+ const resultadoUsuario = await correrQuery(
+ CONSULTAS_EMPLEADOS.OBTENER_ID_USUARIO_POR_EMPLEADO,
+ [idEmpleado]
+ );
+
+ const idUsuario = resultadoUsuario[0]?.idUsuario;
+ if (!idUsuario) {
+ throw new Error(`No se encontró un usuario asociado al empleado con ID ${idEmpleado}`);
+ }
+
+ // 2. Eliminar el usuario
+ await correrQuery('DELETE FROM usuario WHERE idUsuario = ?', [idUsuario]);
+
+ // 3. Eliminar el empleado
+ const resultado = await correrQuery(CONSULTAS_EMPLEADOS.ELIMINAR_EMPLEADO, [idEmpleado]);
+
+ return resultado;
+ } catch {
+ throw new Error('Ocurrio un error al eliminar un empleado');
+ }
+};
diff --git a/Empleados/Datos/Repositorios/repositorioEliminarGrupoEmpleados.js b/Empleados/Datos/Repositorios/repositorioEliminarGrupoEmpleados.js
new file mode 100644
index 00000000..3800661e
--- /dev/null
+++ b/Empleados/Datos/Repositorios/repositorioEliminarGrupoEmpleados.js
@@ -0,0 +1,49 @@
+//RF25 - Eliminar Grupo de Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF25
+
+const db = require('@altertex/util/bd/db');
+const CONSULTAS_GRUPOS = require('@altertex/util/const/consultasGrupoEmpleados');
+
+/**
+ * Elimina un grupo de empleados y sus relaciones con empleados dentro de una transacción.
+ *
+ * Esta función realiza tres operaciones:
+ * 1. Elimina las relaciones entre empleados y el grupo en `empleado_grupo`.
+ * 2. Elimina las relaciones en `set_producto_grupo_empleado`.
+ * 3. Elimina el grupo de la tabla `grupo_empleado`.
+ *
+ * Si alguna de las operaciones falla, se revierte toda la transacción para mantener la integridad de los datos.
+ *
+ * @async
+ * @function eliminarGrupoConTransaccion
+ * @param {number} idGrupo - ID del grupo de empleados a eliminar.
+ * @returns {Promise} - Resultado de la operación MySQL, incluyendo `affectedRows`.
+ * @throws {Error} - Si ocurre un error durante la transacción o eliminación.
+ */
+exports.eliminarGrupoConTransaccion = async (idGrupo) => {
+ const conexion = await db.getConnection();
+
+ try {
+ await conexion.beginTransaction();
+
+ // 1. Eliminar de empleado_grupo
+ await conexion.query(CONSULTAS_GRUPOS.ELIMINAR_EMPLEADO_GRUPO, [idGrupo]);
+
+ // 2. Eliminar de set_producto_grupo_empleado
+ await conexion.query(CONSULTAS_GRUPOS.ELIMINAR_SET_PRODUCTO_GRUPO, [idGrupo]);
+
+ // 3. Eliminar de grupo_empleado
+ const [resultado] = await conexion.query(CONSULTAS_GRUPOS.ELIMINAR_GRUPO, [idGrupo]);
+
+ if (resultado.affectedRows === 0) {
+ throw new Error(`Grupo con ID ${idGrupo} no encontrado`);
+ }
+
+ await conexion.commit();
+ return resultado;
+ } catch (error) {
+ await conexion.rollback();
+ throw error;
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
\ No newline at end of file
diff --git a/Empleados/Datos/Repositorios/repositorioEmpleados.js b/Empleados/Datos/Repositorios/repositorioEmpleados.js
new file mode 100644
index 00000000..6270fb2b
--- /dev/null
+++ b/Empleados/Datos/Repositorios/repositorioEmpleados.js
@@ -0,0 +1,28 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_EMPLEADOS = require('@altertex/util/const/consultasEmpleados');
+
+/**
+ * Función para obtener la lista de empleados de un cliente específico.
+ *
+ * RF17 - Consulta Lista Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF17
+ *
+ * @async
+ * @function obtenerEmpleados
+ * @param {number} idCliente - ID del cliente cuyos empleados se desean consultar.
+ *
+ * @returns {Promise} Lista de empleados del cliente.
+ * - Si no se encuentran empleados, se retorna un array vacío.
+ *
+ * @throws {Error} Si ocurre un error al ejecutar la consulta o si no se encuentran resultados.
+ */
+exports.obtenerEmpleados = async (idCliente) => {
+ const query = CONSULTAS_EMPLEADOS.OBTENER_LISTA;
+
+ try {
+ const empleados = await correrQuery(query, [idCliente]);
+
+ return empleados;
+ } catch {
+ return [];
+ }
+};
diff --git a/Empleados/Datos/Repositorios/repositorioExportarEmpleado.js b/Empleados/Datos/Repositorios/repositorioExportarEmpleado.js
new file mode 100644
index 00000000..f8d7f19a
--- /dev/null
+++ b/Empleados/Datos/Repositorios/repositorioExportarEmpleado.js
@@ -0,0 +1,17 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_EMPLEADOS = require('@altertex/util/const/consultasEmpleados');
+
+/**
+ * Consulta la lista de empleados seleccionados de un cliente para exportar en CSV.
+ *
+ * @param {number} idCliente
+ * @param {number[]} idsEmpleado
+ * @returns {Promise>}
+ *
+ * @see [RF59 - Documentación de requisitos](https://codeandco-wiki.netlify.app/docs/next/proyectos/textiles/documentacion/requisitos/RF59)
+ */
+exports.obtenerEmpleadosExportacion = (idCliente, idsEmpleado) => {
+ const placeholders = idsEmpleado.map(() => '?').join(', ');
+ const query = CONSULTAS_EMPLEADOS.OBTENER_DATOS_EXPORTACION.replace('__IDS__', placeholders);
+ return correrQuery(query, [idCliente, ...idsEmpleado]);
+};
\ No newline at end of file
diff --git a/Empleados/Datos/Repositorios/repositorioGrupoDeEmpleados.js b/Empleados/Datos/Repositorios/repositorioGrupoDeEmpleados.js
new file mode 100644
index 00000000..184fc061
--- /dev/null
+++ b/Empleados/Datos/Repositorios/repositorioGrupoDeEmpleados.js
@@ -0,0 +1,61 @@
+/**
+ * @file grupoEmpleados.repositorio.js
+ * @description
+ * Contiene funciones para consultar y validar grupos de empleados asociados a un cliente.
+ * Incluye lógica para obtener todos los grupos de un cliente y verificar duplicados por nombre.
+ *
+ * RF22 - Consulta Lista de Grupo Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF22
+ */
+
+// Importación de utilidades para consultas a base de datos.
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_GRUPO_EMPLEADOS = require('@altertex/util/const/consultasGrupoEmpleados');
+const conexion = require('@altertex/util/bd/db');
+
+/**
+ * Obtiene la lista de grupos de empleados asociados a un cliente específico.
+ *
+ * @async
+ * @function obtenerGrupoDeEmpleados
+ * @param {number} idCliente - ID del cliente cuyo grupo de empleados se desea consultar.
+ * @returns {Promise>} Retorna un arreglo con los grupos encontrados, o vacío si no hay resultados.
+ *
+ * @description
+ * Ejecuta una consulta SQL que retorna los grupos de empleados de un cliente.
+ * Si ocurre un error durante la ejecución, se captura y se retorna un arreglo vacío.
+ */
+exports.obtenerGrupoDeEmpleados = async (idCliente) => {
+ const query = CONSULTAS_GRUPO_EMPLEADOS.OBTENER_LISTA;
+
+ try {
+ const gruposDeEmpleados = await correrQuery(query, [idCliente]);
+ return gruposDeEmpleados;
+ } catch {
+ return [];
+ }
+};
+
+/**
+ * Verifica si ya existe un grupo de empleados con el mismo nombre para un cliente determinado.
+ *
+ * @function existeGrupoConNombre
+ * @param {string} nombreGrupo - Nombre del grupo a verificar.
+ * @param {number} idCliente - ID del cliente propietario del grupo.
+ * @returns {Promise} Retorna true si el grupo ya existe, false si no.
+ *
+ * @description
+ * Ejecuta una consulta SQL para validar si el nombre del grupo ya está registrado para ese cliente,
+ * útil para evitar duplicados al momento de crear nuevos grupos.
+ */
+exports.existeGrupoConNombre = (nombreGrupo, idCliente) => {
+ return new Promise((resolve, reject) => {
+ conexion.query(
+ CONSULTAS_GRUPO_EMPLEADOS.VALIDAR_NOMBRE_REPETIDO,
+ [nombreGrupo.trim(), idCliente],
+ (err, resultados) => {
+ if (err) return reject(err);
+ resolve(resultados.length > 0);
+ },
+ );
+ });
+};
\ No newline at end of file
diff --git a/Empleados/Datos/Repositorios/repositorioImportarEmpleado.js b/Empleados/Datos/Repositorios/repositorioImportarEmpleado.js
new file mode 100644
index 00000000..9a0741c1
--- /dev/null
+++ b/Empleados/Datos/Repositorios/repositorioImportarEmpleado.js
@@ -0,0 +1,141 @@
+const db = require('@altertex/util/bd/db');
+const DEFAULT_ROLE_ID = 3; // ID del rol por defecto para empleados
+const CONSULTAS_IMPORTAR_EMPLEADOS = require('@altertex/util/const/consultasImportarEmpleados');
+/**
+ * Importa en bloque múltiples empleados, creando sus usuarios, asignando rol y vinculación con clientes.
+ *
+ * @async
+ * @function importarEmpleadosMasivo
+ * @param {Array} empleados - Lista de objetos con los datos de usuario y empleado.
+ * @param {string} empleados[].nombreCompleto - Nombre completo del usuario.
+ * @param {string} empleados[].correoElectronico - Correo electrónico único del usuario.
+ * @param {string} empleados[].contrasena - Contraseña en texto plano (ya hasheada previo a la llamada).
+ * @param {string} empleados[].numeroTelefono - Teléfono del usuario (exactamente 10 dígitos).
+ * @param {string} empleados[].direccion - Dirección del usuario.
+ * @param {string} empleados[].fechaNacimiento - Fecha de nacimiento (YYYY-MM-DD).
+ * @param {string} empleados[].genero - Género del usuario.
+ * @param {boolean} empleados[].estatus - Estatus del usuario (true = activo, false = inactivo).
+ * @param {number|Array} empleados[].idCliente - Uno o varios IDs de cliente asociados.
+ * @param {string} empleados[].numeroEmergencia - Teléfono de emergencia.
+ * @param {string} empleados[].areaTrabajo - Área de trabajo del empleado.
+ * @param {string} empleados[].posicion - Puesto o cargo del empleado.
+ * @param {number} empleados[].cantidadPuntos - Puntos acumulados del empleado.
+ * @param {string} empleados[].antiguedad - Fecha de antigüedad/ingreso (YYYY-MM-DD).
+ * @throws {Error} Si el parámetro "empleados" no es un array válido o está vacío.
+ * @throws {Error} Si se detectan correos o teléfonos duplicados en la base de datos.
+ * @throws {Error} Si ocurre cualquier fallo durante la inserción en la transacción.
+ *
+ * @returns {Promise} Resuelve sin valor si la importación fue exitosa.
+ */
+exports.importarEmpleadosMasivo = async (empleados) => {
+ if (!Array.isArray(empleados) || empleados.length === 0) {
+ throw new Error('No se recibió ningún empleado para importar.');
+ }
+
+ // Obtenemos la conexión del pool
+ const conn = await db.getConnection();
+
+ try {
+ // Iniciamos la transacción
+ await conn.beginTransaction();
+
+ // 1) Validar correos duplicados en bloque
+ const correos = empleados.map((elemento) => elemento.correoElectronico);
+ const [correosExistentes] = await conn.query(
+ CONSULTAS_IMPORTAR_EMPLEADOS.VALIDAR_CORREOS_DUPLICADOS,
+ [correos]
+ );
+ if (correosExistentes.length > 0) {
+ const lista = correosExistentes.map((fila) => fila.correoElectronico).join(', ');
+ throw new Error(`Correos ya registrados: ${lista}`);
+ }
+
+ // 2) Validar teléfonos duplicados en bloque
+ const telefonos = empleados.map((elemento) => elemento.numeroTelefono);
+ const [telefonosExistentes] = await conn.query(
+ CONSULTAS_IMPORTAR_EMPLEADOS.VALIDAR_TELEFONO_DUPLICADO,
+ [telefonos]
+ );
+ if (telefonosExistentes.length > 0) {
+ const lista = telefonosExistentes.map((fila) => fila.numeroTelefono).join(', ');
+ throw new Error(`Teléfonos ya registrados: ${lista}`);
+ }
+
+ // 3) Bulk‐insert de usuarios
+ const usuariosValues = empleados.map((elemento) => [
+ elemento.nombreCompleto,
+ elemento.correoElectronico,
+ elemento.contrasena,
+ elemento.numeroTelefono,
+ elemento.direccion,
+ elemento.fechaNacimiento,
+ elemento.genero,
+ elemento.estatus,
+ ]);
+ await conn.query(CONSULTAS_IMPORTAR_EMPLEADOS.INSERTAR_USUARIO_EN_VOLUMEN, [usuariosValues]);
+
+ // 4) Recuperar los IDs generados
+ const [rowsUsuarios] = await conn.query(CONSULTAS_IMPORTAR_EMPLEADOS.OBTENER_ID_GENERADOS, [
+ correos,
+ ]);
+ const idMap = rowsUsuarios.reduce((map, row) => {
+ map[row.correoElectronico] = row.idUsuario;
+ return map;
+ }, {});
+
+ // 5) Bulk‐insert de roles
+ const rolValues = empleados.map((elemento) => [
+ idMap[elemento.correoElectronico],
+ DEFAULT_ROLE_ID,
+ ]);
+ await conn.query(CONSULTAS_IMPORTAR_EMPLEADOS.INSERTAR_ROLES_EN_VOLUMEN, [rolValues]);
+
+ // 6) Bulk‐insert de asociaciones usuario‐cliente
+ const clienteValues = [];
+ empleados.forEach((elemento) => {
+ const idU = idMap[elemento.correoElectronico];
+ const listaClientes = Array.isArray(elemento.idCliente)
+ ? elemento.idCliente
+ : [elemento.idCliente];
+ listaClientes.forEach((idCli) => clienteValues.push([idU, idCli]));
+ });
+ await conn.query(CONSULTAS_IMPORTAR_EMPLEADOS.INSERTAR_USUARIO_CLIENTE_EN_VOLUMEN, [
+ clienteValues,
+ ]);
+
+ // 7) Bulk‐insert de empleados
+ const empValues = empleados.map((elemento) => [
+ idMap[elemento.correoElectronico],
+ elemento.idCliente,
+ elemento.numeroEmergencia,
+ elemento.areaTrabajo,
+ elemento.posicion,
+ parseFloat(elemento.cantidadPuntos),
+ elemento.antiguedad,
+ ]);
+ await conn.query(CONSULTAS_IMPORTAR_EMPLEADOS.INSERTAR_EMPLEADOS_EN_VOLUMEN, [empValues]);
+
+ await conn.commit();
+ } catch (err) {
+ await conn.rollback();
+ const mensajeOriginal = err.message || '';
+
+ // Detectar error por entrada duplicada
+ const entradaDuplicada = mensajeOriginal.match(/Duplicate entry '(.+)' for key '(.+)'/);
+
+ if (entradaDuplicada) {
+ const valorDuplicado = entradaDuplicada[1];
+ const campo = entradaDuplicada[2];
+
+ let campoTraducido = campo;
+ if (campo.includes('correoElectronico')) campoTraducido = 'correo electrónico';
+ else if (campo.includes('telefono')) campoTraducido = 'número de teléfono';
+
+ throw new Error(`La entrada ${campoTraducido} "${valorDuplicado}" esta duplicada`);
+ }
+
+ throw new Error(`Error en importación masiva: ${mensajeOriginal}`);
+ } finally {
+ if (conn) conn.release();
+ }
+};
diff --git a/Empleados/Datos/Repositorios/repositorioLeerGrupoDeEmpleados.js b/Empleados/Datos/Repositorios/repositorioLeerGrupoDeEmpleados.js
new file mode 100644
index 00000000..54831892
--- /dev/null
+++ b/Empleados/Datos/Repositorios/repositorioLeerGrupoDeEmpleados.js
@@ -0,0 +1,58 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_GRUPOS_EMPLEADOS = require('@altertex/util/const/consultasGrupoEmpleados');
+
+/**
+ * Obtiene un grupo de empleados desde la base de datos mediante su ID.
+ *
+ * Ejecuta una consulta SQL y retorna el primer grupo de empleados encontrado o `null` si no existe.
+ *
+ * @param {number|string} idGrupo - ID del grupo a buscar.
+ * @returns {Promise} El grupo de empleados encontrado o `null` si no existe.
+ * @throws {Error} Si ocurre un error al ejecutar la consulta.
+ *
+ * @see RF[23] Lee grupo de empleados -https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF23
+ */
+exports.obtenerGrupoEmpleadosPorId = async (idGrupo) => {
+ const query = CONSULTAS_GRUPOS_EMPLEADOS.LEER_GRUPO;
+ try {
+ const resultado = await correrQuery(query, [idGrupo]);
+
+ if (resultado.length === 0) return null;
+
+ // ✅ Manejo seguro de setProductosActualizar cuando es null o contiene objetos con valores null
+ const setProductosOriginal = resultado[0].setProductosActualizar || [];
+
+ // Filtrar objetos que tienen id null (cuando no hay datos reales)
+ const setProductosValidos = setProductosOriginal.filter((obj) => obj.id !== null);
+
+ const setProductosFiltrados = Object.values(
+ setProductosValidos.reduce((acc, obj) => {
+ acc[obj.id] = obj; // sobrescribe si ya existe ese id
+ return acc;
+ }, {})
+ );
+
+ const grupoEmpleados = {
+ idGrupo: resultado[0].idGrupo,
+ nombre: resultado[0].nombre,
+ descripcion: resultado[0].descripcion,
+ setsProductos: resultado[0].setsProductos ? resultado[0].setsProductos.split(', ') : [],
+ idsSetProductos: resultado[0].idsSetProductos
+ ? resultado[0].idsSetProductos.split(', ').map(Number)
+ : [],
+ empleados: resultado[0].infoEmpleados ? resultado[0].infoEmpleados.split(' || ') : [],
+ idsEmpleados: resultado[0].idsEmpleados
+ ? resultado[0].idsEmpleados.split(',').map(Number)
+ : [],
+ empleadosActualizar: (resultado[0].empleadosActualizar || []).filter(
+ (obj) => obj.id !== null
+ ),
+ setProductosActualizar: setProductosFiltrados, // Ya no necesita validación adicional
+ };
+
+ return grupoEmpleados;
+ } catch (error) {
+ console.error('Error al obtener el grupo de empleados con id:', error);
+ throw error;
+ }
+};
diff --git a/Empleados/Rutas/RutasIndividuales/actualizarEmpleado.routes.js b/Empleados/Rutas/RutasIndividuales/actualizarEmpleado.routes.js
new file mode 100644
index 00000000..5b1496aa
--- /dev/null
+++ b/Empleados/Rutas/RutasIndividuales/actualizarEmpleado.routes.js
@@ -0,0 +1,119 @@
+const express = require('express');
+const ruteador = express.Router();
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+const controlador = require('@altertex/emp/ctrl/actualizarEmpleado.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const revisarPermisos = require('@altertex/util/inter/verificarPermisos');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+//RF[19] Actualizar Empleado - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF19]
+
+/**
+ * @swagger
+ * /api/empleados/actualizar:
+ * put:
+ * summary: Actualiza la información de uno o varios empleados.
+ * tags:
+ * - Empleados
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: array
+ * description: Array de objetos con información de empleados a actualizar
+ * items:
+ * type: object
+ * required:
+ * - idEmpleado
+ * - numeroEmergencia
+ * - areaTrabajo
+ * - posicion
+ * - cantidadPuntos
+ * - antiguedad
+ * properties:
+ * id:
+ * type: integer
+ * example: 50
+ * idEmpleado:
+ * type: integer
+ * example: 50
+ * idUsuario:
+ * type: integer
+ * example: 30
+ * nombreCompleto:
+ * type: string
+ * example: "Angel Romero"
+ * correoElectronico:
+ * type: string
+ * example: "aromero@google.com"
+ * numeroEmergencia:
+ * type: string
+ * example: "9876543214"
+ * areaTrabajo:
+ * type: string
+ * example: "Ventas"
+ * posicion:
+ * type: string
+ * example: "Auxiliar"
+ * cantidadPuntos:
+ * type: integer
+ * example: 2
+ * antiguedad:
+ * type: string
+ * example: "2000-02-10"
+ * responses:
+ * 200:
+ * description: Información del empleado actualizada correctamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Actualización exitosa."
+ * datos:
+ * type: array
+ * items:
+ * type: object
+ * 400:
+ * description: Error en los datos enviados o en la actualización.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Error al actualizar"
+ * x-codeSamples:
+ * - lang: JavaScript
+ * label: cURL
+ * source: |
+ * # Ejemplo enviando un array de empleados
+ * curl -X PUT "https://tu-api.com/api/empleados/actualizar" \
+ * -H "x-api-key: TU_API_KEY" \
+ * -H "Authorization: Bearer TU_TOKEN" \
+ * -H "Content-Type: application/json" \
+ * -d '[{"id":50,"idUsuario":30,"nombreCompleto":"Angel Romero","correoElectronico":"aromero@google.com","numeroEmergencia":"9876543214","areaTrabajo":"Ventas","posicion":"Auxiliar","cantidadPuntos":2,"antiguedad":"2000-02-10","idEmpleado":50}]'
+ */
+
+ruteador.put(
+ RUTAS.EMPLEADOS.ACTUALIZAR,
+ revisarApiKey(),
+ validarYSanitizar,
+ autorizarToken,
+ limitePeticionesDiarias,
+ revisarPermisos(PERMISOS.ACTUALIZAR_EMPLEADO),
+ controlador.actualizarEmpleado
+);
+
+module.exports = ruteador;
diff --git a/Empleados/Rutas/RutasIndividuales/actualizarGrupoEmpleados.routes.js b/Empleados/Rutas/RutasIndividuales/actualizarGrupoEmpleados.routes.js
new file mode 100644
index 00000000..d4c530bd
--- /dev/null
+++ b/Empleados/Rutas/RutasIndividuales/actualizarGrupoEmpleados.routes.js
@@ -0,0 +1,118 @@
+const express = require('express');
+const ruteador = express.Router();
+const RUTAS = require('@altertex/util/const/rutas');
+const PERMISOS = require('@altertex/util/const/permisos');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const controlador = require('@altertex/emp/ctrl/actualizarGrupoEmpleado.controller');
+// RF[24] Actualiza grupo empleado - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF24]
+
+/**
+ * @swagger
+ * /api/empleados/actualizar-grupo:
+ * put:
+ * summary: Actualiza un grupo de empleados
+ * description: Actualiza el nombre, la descripción, los empleados y los sets de productos asociados a un grupo de empleados existente.
+ * tags:
+ * - Grupos de Empleados
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * required:
+ * - idGrupoEmpleado
+ * - nombre
+ * - descripcion
+ * - empleados
+ * - setsDeProductos
+ * properties:
+ * idGrupoEmpleado:
+ * type: integer
+ * example: 1
+ * nombre:
+ * type: string
+ * example: "Grupo Administrativo"
+ * descripcion:
+ * type: string
+ * example: "Grupo para empleados administrativos"
+ * empleados:
+ * type: array
+ * items:
+ * type: integer
+ * example: [101, 102, 103]
+ * setsDeProductos:
+ * type: array
+ * items:
+ * type: integer
+ * example: [201, 202]
+ * responses:
+ * 200:
+ * description: Se actualizó correctamente el grupo de empleados.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Se actualizo correctamente el grupo de empleados.
+ * 400:
+ * description: Error de validación o datos inválidos.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * examples:
+ * Formato inválido:
+ * value:
+ * mensaje: No se obtuvieron los datos correctamente.
+ * Verificación de empleados fallida:
+ * value:
+ * mensaje: Algunos empleados no pertenecen al mismo cliente que el grupo.
+ * Verificación de sets fallida:
+ * value:
+ * mensaje: Algunos sets de productos no pertenecen al cliente de este grupo.
+ * Actualización fallida:
+ * value:
+ * mensaje: Error actualizando el grupo de empleados.
+ * 403:
+ * description: No tiene permisos para realizar esta acción.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No tiene permiso para consultar grupos de empleados de este cliente.
+ * 500:
+ * description: Error interno del servidor.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Ocurrió un error al actualizar el grupo de empleados.
+ */
+ruteador.put(
+ RUTAS.EMPLEADOS.ACTUALIZAR_GRUPO_EMPLEADO,
+ revisarApiKey(),
+ autorizarToken,
+ verificarPermisos(PERMISOS.ACTUALIZAR_GRUPO_EMPLEADOS),
+ validarYSanitizar,
+ controlador.actualizarGrupoEmpleados
+);
+
+module.exports = ruteador;
diff --git a/Empleados/Rutas/RutasIndividuales/consultarLista.routes.js b/Empleados/Rutas/RutasIndividuales/consultarLista.routes.js
new file mode 100644
index 00000000..b8afc64d
--- /dev/null
+++ b/Empleados/Rutas/RutasIndividuales/consultarLista.routes.js
@@ -0,0 +1,116 @@
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/emp/ctrl/consultarLista.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * RF17 - Consulta Lista Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF17
+ */
+
+/**
+ * @swagger
+ * /api/empleados/consultar-lista:
+ * post:
+ * summary: Consulta la lista de empleados de un cliente
+ * description: |
+ * Este endpoint permite obtener la lista completa de empleados registrados para un cliente específico.
+ * La consulta está protegida por API Key, token de sesión y verificación de permisos.
+ * tags: [Empleados]
+ * security:
+ * - ApiKeyAuth: []
+ * responses:
+ * 200:
+ * description: Lista de empleados obtenida exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Lista de empleados obtenida exitosamente."
+ * empleados:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * nombreCompleto:
+ * type: string
+ * example: "Ana Martínez"
+ * correoElectronico:
+ * type: string
+ * example: "ana.martinez@example.com"
+ * idEmpleado:
+ * type: integer
+ * example: 3
+ * idUsuario:
+ * type: integer
+ * example: 3
+ * idCliente:
+ * type: integer
+ * example: 101
+ * numeroEmergencia:
+ * type: string
+ * example: "5587654321"
+ * areaTrabajo:
+ * type: string
+ * example: "Ventas"
+ * posicion:
+ * type: string
+ * example: "Asesor Comercial"
+ * cantidadPuntos:
+ * type: string
+ * example: "28.00"
+ * antiguedad:
+ * type: string
+ * format: date-time
+ * example: "2020-06-15T05:00:00.000Z"
+ * 400:
+ * description: Los parámetros enviados no son válidos.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Parámetros inválidos."
+ * 404:
+ * description: No se encontraron empleados registrados para el cliente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "No se encontraron resultados."
+ * 500:
+ * description: Error interno al intentar consultar la lista de empleados.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Error al consultar empleados."
+ */
+
+ruteador.post(
+ RUTAS.EMPLEADOS.CONSULTAR_LISTA,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CONSULTAR_EMPLEADOS),
+ controlador.consultarLista
+);
+
+module.exports = ruteador;
diff --git a/Empleados/Rutas/RutasIndividuales/consultarListaGrupos.routes.js b/Empleados/Rutas/RutasIndividuales/consultarListaGrupos.routes.js
new file mode 100644
index 00000000..3e2f7859
--- /dev/null
+++ b/Empleados/Rutas/RutasIndividuales/consultarListaGrupos.routes.js
@@ -0,0 +1,117 @@
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/emp/ctrl/consultarListaGrupos.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * RF22 - Consulta Lista de Grupo Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF22
+ */
+
+/**
+ * @swagger
+ * /api/empleados/consultar-grupo:
+ * post:
+ * summary: Consulta la lista de grupos de empleados de un cliente
+ * description: |
+ * Este endpoint permite consultar los grupos de empleados asociados a un cliente, especificando un límite
+ * y un offset para la paginación de resultados.
+ * tags: [Empleados]
+ * security:
+ * - ApiKeyAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * limit:
+ * type: integer
+ * description: Número máximo de resultados a devolver.
+ * example: 10
+ * offset:
+ * type: integer
+ * description: Número de resultados a omitir (para paginación).
+ * example: 0
+ * responses:
+ * 200:
+ * description: Consulta exitosa. Se devuelve la lista de grupos de empleados.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Lista de grupos de empleados obtenida exitosamente."
+ * grupoEmpleados:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * idGrupo:
+ * type: integer
+ * example: 3
+ * geNombre:
+ * type: string
+ * example: "Calidad Toyota"
+ * descripcion:
+ * type: string
+ * example: "Encargados de la calidad y los controles en el proceso de fabricación."
+ * idSetProducto:
+ * type: integer
+ * example: 3
+ * spNombre:
+ * type: string
+ * example: "Set Calidad Toyota"
+ * totalEmpleados:
+ * type: integer
+ * example: 1
+ * 400:
+ * description: Los parámetros 'limit' o 'offset' son inválidos o faltan.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Parámetros inválidos."
+ * 404:
+ * description: No se encontraron resultados para la consulta.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "No se encontraron resultados."
+ * 500:
+ * description: Error en el servidor al intentar obtener la lista de empleados.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Error al consultar empleados."
+ */
+
+ruteador.post(
+ RUTAS.EMPLEADOS.CONSULTAR_GRUPO,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CONSULTAR_GRUPOS_EMPLEADOS),
+ controlador.consultarLista
+);
+
+module.exports = ruteador;
diff --git a/Empleados/Rutas/RutasIndividuales/crearEmpleado.routes.js b/Empleados/Rutas/RutasIndividuales/crearEmpleado.routes.js
new file mode 100644
index 00000000..f883d48f
--- /dev/null
+++ b/Empleados/Rutas/RutasIndividuales/crearEmpleado.routes.js
@@ -0,0 +1,204 @@
+//RF16 - Crear Empleado - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF16]
+
+const express = require('express');
+const ruteador = express.Router();
+
+const controlador = require('@altertex/emp/ctrl/crearEmpleado.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+/**
+ * @swagger
+ * /api/empleados/crear:
+ * post:
+ * summary: Crea un nuevo empleado.
+ * tags:
+ * - Empleados
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * oneOf:
+ * - type: object
+ * description: Información del nuevo empleado a crear directamente en el body
+ * required:
+ * - idUsuario
+ * - idCliente
+ * - nombreCompleto
+ * - correoElectronico
+ * - numeroEmergencia
+ * - areaTrabajo
+ * - posicion
+ * - cantidadPuntos
+ * - antiguedad
+ * properties:
+ * idUsuario:
+ * type: integer
+ * example: 30
+ * idCliente:
+ * type: integer
+ * example: 10
+ * nombreCompleto:
+ * type: string
+ * example: "Carlos Pérez"
+ * correoElectronico:
+ * type: string
+ * example: "cperez@google.com"
+ * numeroEmergencia:
+ * type: string
+ * example: "9876543214"
+ * areaTrabajo:
+ * type: string
+ * example: "Producción"
+ * posicion:
+ * type: string
+ * example: "Operador"
+ * cantidadPuntos:
+ * type: integer
+ * example: 0
+ * antiguedad:
+ * type: string
+ * example: "2024-01-01"
+ * - type: object
+ * properties:
+ * empleados:
+ * oneOf:
+ * - type: object
+ * description: Array único con información del empleado
+ * required:
+ * - idUsuario
+ * - idCliente
+ * - nombreCompleto
+ * - correoElectronico
+ * - numeroEmergencia
+ * - areaTrabajo
+ * - posicion
+ * - cantidadPuntos
+ * - antiguedad
+ * properties:
+ * idUsuario:
+ * type: integer
+ * example: 30
+ * idCliente:
+ * type: integer
+ * example: 10
+ * nombreCompleto:
+ * type: string
+ * example: "Carlos Pérez"
+ * correoElectronico:
+ * type: string
+ * example: "cperez@google.com"
+ * numeroEmergencia:
+ * type: string
+ * example: "9876543214"
+ * areaTrabajo:
+ * type: string
+ * example: "Producción"
+ * posicion:
+ * type: string
+ * example: "Operador"
+ * cantidadPuntos:
+ * type: integer
+ * example: 0
+ * antiguedad:
+ * type: string
+ * example: "2024-01-01"
+ * - type: array
+ * description: Array de objetos con información de empleados
+ * items:
+ * type: object
+ * required:
+ * - idUsuario
+ * - idCliente
+ * - nombreCompleto
+ * - correoElectronico
+ * - numeroEmergencia
+ * - areaTrabajo
+ * - posicion
+ * - cantidadPuntos
+ * - antiguedad
+ * properties:
+ * idUsuario:
+ * type: integer
+ * example: 30
+ * idCliente:
+ * type: integer
+ * example: 10
+ * nombreCompleto:
+ * type: string
+ * example: "Carlos Pérez"
+ * correoElectronico:
+ * type: string
+ * example: "cperez@google.com"
+ * numeroEmergencia:
+ * type: string
+ * example: "9876543214"
+ * areaTrabajo:
+ * type: string
+ * example: "Producción"
+ * posicion:
+ * type: string
+ * example: "Operador"
+ * cantidadPuntos:
+ * type: integer
+ * example: 0
+ * antiguedad:
+ * type: string
+ * example: "2024-01-01"
+ * responses:
+ * 201:
+ * description: Empleado creado correctamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Empleado creado exitosamente."
+ * datos:
+ * type: array
+ * items:
+ * type: object
+ * 400:
+ * description: Error en los datos enviados o en la creación.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Error al crear empleado"
+ * x-codeSamples:
+ * - lang: JavaScript
+ * label: cURL
+ * source: |
+ * # Ejemplo enviando datos directamente
+ * curl -X POST "https://tu-api.com/api/empleados/crear" \
+ * -H "x-api-key: TU_API_KEY" \
+ * -H "Authorization: Bearer TU_TOKEN" \
+ * -H "Content-Type: application/json" \
+ * -d '{"idUsuario":30,"idCliente":10,"nombreCompleto":"Carlos Pérez","correoElectronico":"cperez@google.com","numeroEmergencia":"9876543214","areaTrabajo":"Producción","posicion":"Operador","cantidadPuntos":0,"antiguedad":"2024-01-01"}'
+ */
+
+ruteador.post(
+ RUTAS.EMPLEADOS.CREAR,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ validarYSanitizar,
+ verificarPermisos(PERMISOS.CREAR_EMPLEADO),
+ controlador.crearEmpleado
+);
+
+module.exports = ruteador;
diff --git a/Empleados/Rutas/RutasIndividuales/crearGrupoEmpleados.routes.js b/Empleados/Rutas/RutasIndividuales/crearGrupoEmpleados.routes.js
new file mode 100644
index 00000000..24ee338d
--- /dev/null
+++ b/Empleados/Rutas/RutasIndividuales/crearGrupoEmpleados.routes.js
@@ -0,0 +1,102 @@
+// RF21 - Crear Grupo de Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF21
+
+/**
+ * @file crearGrupoEmpleados.routes.js
+ * @description
+ * Define la ruta para crear un grupo de empleados.
+ * Aplica middlewares de validación, autenticación y autorización antes de delegar al controlador.
+ */
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/emp/ctrl/crearGrupoEmpleados.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/empleados/crear-grupo:
+ * post:
+ * summary: Crear un grupo de empleados.
+ * description: Crea un nuevo grupo de empleados y asigna empleados a ese grupo.
+ * tags:
+ * - Empleados
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * nombreGrupo:
+ * type: string
+ * example: "Grupo de Ventas"
+ * descripcion:
+ * type: string
+ * example: "Grupo encargado de las ventas del mes de enero"
+ * idCliente:
+ * type: integer
+ * example: 123
+ * listaEmpleados:
+ * type: array
+ * items:
+ * type: integer
+ * example: [1, 2, 3]
+ * responses:
+ * 201:
+ * description: Grupo de empleados creado exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Grupo de empleados creado exitosamente."
+ * idGrupo:
+ * type: integer
+ * example: 456
+ * 400:
+ * description: Datos incompletos o inválidos.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Faltan datos requeridos: nombre del grupo o lista de empleados."
+ * 500:
+ * description: Error interno al crear el grupo de empleados.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Ocurrió un error al crear el grupo de empleados."
+ */
+
+// Ruta para crear grupo de empleados
+ruteador.post(
+ RUTAS.EMPLEADOS.CREAR_GRUPO,
+ validarYSanitizar,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CREAR_GRUPO_EMPLEADOS),
+ controlador.crearGrupoEmpleados
+);
+
+// Exportación del ruteador
+module.exports = ruteador;
diff --git a/Empleados/Rutas/RutasIndividuales/eliminarEmpleado.routes.js b/Empleados/Rutas/RutasIndividuales/eliminarEmpleado.routes.js
new file mode 100644
index 00000000..2f38cf65
--- /dev/null
+++ b/Empleados/Rutas/RutasIndividuales/eliminarEmpleado.routes.js
@@ -0,0 +1,80 @@
+// RF[20] Elimina empleado - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF20
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/emp/ctrl/eliminarEmpleado.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/empleados/eliminar:
+ * delete:
+ * summary: Eliminar uno o varios empleados.
+ * description: Elimina empleados según su ID. Requiere autenticación y permisos.
+ * tags:
+ * - Empleados
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * idsEmpleado:
+ * type: array
+ * items:
+ * type: integer
+ * example: [3, 5, 10]
+ * responses:
+ * 200:
+ * description: Empleados eliminados exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Empleados eliminados correctamente.
+ * 404:
+ * description: Empleados no encontrados.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No se encontraron los empleados especificados.
+ * 500:
+ * description: Error interno al eliminar empleados.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error al eliminar empleados.
+ */
+
+ruteador.delete(
+ RUTAS.EMPLEADOS.ELIMINAR_EMPLEADO,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.ELIMINAR_EMPLEADO),
+ controlador.eliminarEmpleado
+);
+
+module.exports = ruteador;
\ No newline at end of file
diff --git a/Empleados/Rutas/RutasIndividuales/eliminarGrupoEmpleados.routes.js b/Empleados/Rutas/RutasIndividuales/eliminarGrupoEmpleados.routes.js
new file mode 100644
index 00000000..61bab347
--- /dev/null
+++ b/Empleados/Rutas/RutasIndividuales/eliminarGrupoEmpleados.routes.js
@@ -0,0 +1,86 @@
+//RF25 - Eliminar Grupo de Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF25
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/emp/ctrl/eliminarGrupoEmpleados.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/empleados/eliminar-grupo:
+ * post:
+ * tags:
+ * - Empleados
+ * summary: Eliminar uno o varios grupos de empleados
+ * description: |
+ * Elimina uno o más grupos de empleados, junto con sus relaciones asociadas.
+ * Requiere autenticación por API Key y Token JWT, además de permisos específicos.
+ * **Requisito funcional:** [RF25 - Eliminar Grupo de Empleados](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF25)
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * required:
+ * - idsGrupo
+ * properties:
+ * idsGrupo:
+ * type: array
+ * items:
+ * type: integer
+ * description: Lista de IDs de grupos a eliminar
+ * example:
+ * idsGrupo: [1, 2, 3]
+ * responses:
+ * 200:
+ * description: Grupos eliminados exitosamente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Grupo de empleados eliminado exitosamente.
+ * 400:
+ * description: Solicitud inválida (por ejemplo, sin IDs o formato incorrecto)
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error al eliminar grupo de empleados.
+ * 500:
+ * description: Error inesperado del servidor
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error interno al procesar la eliminación.
+ */
+
+ruteador.post(
+ RUTAS.EMPLEADOS.ELIMINAR_GRUPO,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.ELIMINAR_GRUPO_EMPLEADOS),
+ controlador.eliminarGrupoEmpleados
+);
+
+module.exports = ruteador;
diff --git a/Empleados/Rutas/RutasIndividuales/exportarEmpleados.routes.js b/Empleados/Rutas/RutasIndividuales/exportarEmpleados.routes.js
new file mode 100644
index 00000000..a51ccfe8
--- /dev/null
+++ b/Empleados/Rutas/RutasIndividuales/exportarEmpleados.routes.js
@@ -0,0 +1,77 @@
+//RF59 - Exportar Empleados- https://codeandco-wiki.netlify.app/docs/next/proyectos/textiles/documentacion/requisitos/RF59
+
+/**
+ * @swagger
+ * /api/empleados/exportar:
+ * post:
+ * summary: Exporta la lista completa de empleados en formato CSV.
+ * tags:
+ * - Empleados
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * parameters:
+ * - in: header
+ * name: x-api-key
+ * required: true
+ * schema:
+ * type: string
+ * description: Clave de API
+ * - in: header
+ * name: Authorization
+ * required: true
+ * schema:
+ * type: string
+ * description: Token JWT con formato "Bearer "
+ * responses:
+ * 200:
+ * description: Archivo CSV generado correctamente.
+ * content:
+ * text/csv:
+ * schema:
+ * type: string
+ * format: binary
+ * 204:
+ * description: No hay empleados para exportar.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No hay empleados para exportar.
+ * 400:
+ * description: Error interno del servidor al exportar empleados.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error al exportar la lista de empleados.
+ */
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/emp/ctrl/exportarEmpleados.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+ruteador.post(
+ RUTAS.EMPLEADOS.EXPORTAR_EMPLEADOS,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ validarYSanitizar,
+ verificarPermisos(PERMISOS.EXPORTAR_EMPLEADOS),
+ controlador.exportarEmpleados
+);
+
+module.exports = ruteador;
\ No newline at end of file
diff --git a/Empleados/Rutas/RutasIndividuales/importarEmpleados.routes.js b/Empleados/Rutas/RutasIndividuales/importarEmpleados.routes.js
new file mode 100644
index 00000000..9fd467f5
--- /dev/null
+++ b/Empleados/Rutas/RutasIndividuales/importarEmpleados.routes.js
@@ -0,0 +1,170 @@
+//RF57 - Importar Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF57
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/emp/ctrl/importarEmpleados.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+/**
+ * @swagger
+ * /api/empleados/importar-empleados:
+ * post:
+ * summary: Importa múltiples empleados desde un JSON derivado de CSV.
+ * tags:
+ * - Empleados
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * parameters:
+ * - in: header
+ * name: x-api-key
+ * required: true
+ * schema:
+ * type: string
+ * description: Clave de API
+ * - in: header
+ * name: Authorization
+ * required: true
+ * schema:
+ * type: string
+ * description: Token JWT "Bearer "
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: array
+ * items:
+ * type: object
+ * required:
+ * - nombreCompleto
+ * - correoElectronico
+ * - contrasena
+ * - numeroTelefono
+ * - direccion
+ * - fechaNacimiento
+ * - genero
+ * - estatus
+ * - idCliente
+ * - numeroEmergencia
+ * - areaTrabajo
+ * - posicion
+ * - cantidadPuntos
+ * - antiguedad
+ * properties:
+ * nombreCompleto:
+ * type: string
+ * example: Juan Pérez
+ * correoElectronico:
+ * type: string
+ * format: email
+ * example: juan.perez@correo.com
+ * contrasena:
+ * type: string
+ * example: Password123!
+ * numeroTelefono:
+ * type: string
+ * example: 5512345678
+ * direccion:
+ * type: string
+ * example: Av. Siempre Viva 742
+ * fechaNacimiento:
+ * type: string
+ * format: date
+ * example: 1990-05-12
+ * genero:
+ * type: string
+ * example: M
+ * estatus:
+ * type: boolean
+ * example: true
+ * idCliente:
+ * oneOf:
+ * - type: integer
+ * - type: array
+ * items:
+ * type: integer
+ * example: 101
+ * numeroEmergencia:
+ * type: string
+ * example: 5512340000
+ * areaTrabajo:
+ * type: string
+ * example: Logística
+ * posicion:
+ * type: string
+ * example: Analista de datos
+ * cantidadPuntos:
+ * type: number
+ * example: 120.5
+ * antiguedad:
+ * type: string
+ * format: date
+ * example: 2020-01-15
+ * responses:
+ * 200:
+ * description: Todos los empleados importados correctamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Todos los empleados importados correctamente.
+ * 207:
+ * description: Importación parcial con errores en algunas filas.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Importación parcial con errores.
+ * errores:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * fila:
+ * oneOf:
+ * - type: integer
+ * - type: string
+ * example: 3
+ * error:
+ * type: string
+ * example: Correo inválido.
+ * 400:
+ * description: Petición inválida, cuerpo vacío o no es un array.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No se recibieron empleados.
+ * 499:
+ * description: Cliente abortó la petición.
+ * 500:
+ * description: Error interno del servidor.
+ */
+
+ruteador.post(
+ RUTAS.EMPLEADOS.IMPORTAR_EMPLEADOS,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ validarYSanitizar,
+ verificarPermisos(PERMISOS.IMPORTAR_EMPLEADOS),
+ controlador.importarEmpleados
+);
+
+module.exports = ruteador;
diff --git a/Empleados/Rutas/RutasIndividuales/leerGrupoEmpleados.routes.js b/Empleados/Rutas/RutasIndividuales/leerGrupoEmpleados.routes.js
new file mode 100644
index 00000000..48da58bc
--- /dev/null
+++ b/Empleados/Rutas/RutasIndividuales/leerGrupoEmpleados.routes.js
@@ -0,0 +1,117 @@
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/emp/ctrl/leerGrupoEmpleados.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * RF[23] Lee grupo de empleados -https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF23
+ */
+
+/**
+ * @swagger
+ * /api/empleados/leer-grupo:
+ * post:
+ * summary: Leer grupo de empleados.
+ * description: |
+ * Obtiene información sobre un grupo de empleados basado en los parámetros proporcionados. Requiere autenticación y permisos específicos.
+ * tags: [Empleados]
+ * security:
+ * - ApiKeyAuth: []
+ * responses:
+ * 200:
+ * description: Información del grupo de empleados obtenida exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Grupo de empleados obtenido correctamente.
+ * data:
+ * type: object
+ * properties:
+ * idGrupo:
+ * type: integer
+ * example: 1
+ * nombre:
+ * type: string
+ * example: "Grupo Ventas"
+ * descripcion:
+ * type: string
+ * example: "Grupo encargado de las ventas regionales"
+ * setsProductos:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * idSetProducto:
+ * type: integer
+ * example: 101
+ * nombreSet:
+ * type: string
+ * example: "Set de Productos A"
+ * empleados:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * idEmpleado:
+ * type: integer
+ * example: 201
+ * nombre:
+ * type: string
+ * example: "Juan Pérez"
+ * departamento:
+ * type: string
+ * example: "Ventas"
+ * 400:
+ * description: Solicitud inválida.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Parámetros inválidos.
+ * 401:
+ * description: No autorizado.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No tienes permisos para realizar esta acción.
+ * 500:
+ * description: Error interno del servidor.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error al obtener el grupo de empleados.
+ */
+ruteador.post(
+ RUTAS.EMPLEADOS.LEER_GRUPO,
+ validarYSanitizar,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.LEER_GRUPO_EMPLEADOS),
+ controlador.leerGrupoEmpleados
+);
+
+module.exports = ruteador;
diff --git a/Empleados/Rutas/indexEmpleados.routes.js b/Empleados/Rutas/indexEmpleados.routes.js
new file mode 100644
index 00000000..7f39b6f5
--- /dev/null
+++ b/Empleados/Rutas/indexEmpleados.routes.js
@@ -0,0 +1,39 @@
+const express = require('express');
+const ruteador = express.Router();
+const rutasConsultarListaGrupos = require('@altertex/emp/rutasInd/consultarListaGrupos.routes');
+const rutasCrearEmpleado = require('@altertex/emp/rutasInd/crearEmpleado.routes');
+const rutasConsultarLista = require('@altertex/emp/rutasInd/consultarLista.routes');
+const rutasEliminarGrupo = require('@altertex/emp/rutasInd/eliminarGrupoEmpleados.routes');
+const rutasEliminarEmpleado = require('@altertex/emp/rutasInd/eliminarEmpleado.routes');
+const rutasImportarEmpleados = require('@altertex/emp/rutasInd/importarEmpleados.routes');
+const rutasExportarEmpleados = require('@altertex/emp/rutasInd/exportarEmpleados.routes');
+const rutasLeerGrupoEmpleados = require('@altertex/emp/rutasInd/leerGrupoEmpleados.routes');
+const rutasCrearGrupo = require('@altertex/emp/rutasInd/crearGrupoEmpleados.routes');
+const rutasActualizarEmpleado = require('@altertex/emp/rutasInd/actualizarEmpleado.routes');
+const rutasActualizarGrupo = require('@altertex/emp/rutasInd/actualizarGrupoEmpleados.routes');
+
+const RUTAS = require('@altertex/util/const/rutas');
+
+//RF22 - Consulta Lista de Grupo Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF22
+ruteador.use(RUTAS.EMPLEADOS.BASE, rutasConsultarListaGrupos);
+//RF17 - Consulta Lista Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF17
+ruteador.use(RUTAS.EMPLEADOS.BASE, rutasConsultarLista);
+//RF25 - Eliminar Grupo de Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF25
+ruteador.use(RUTAS.EMPLEADOS.BASE, rutasEliminarGrupo);
+//RF20 - Eliminar Empleado - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF20
+ruteador.use(RUTAS.EMPLEADOS.BASE, rutasEliminarEmpleado);
+//RF57 - Importar Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF57
+ruteador.use(RUTAS.EMPLEADOS.BASE, rutasImportarEmpleados);
+//RF23 Lee grupo de empleados -https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF23
+ruteador.use(RUTAS.EMPLEADOS.BASE, rutasLeerGrupoEmpleados);
+//RF21 - Crear Grupo de Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF21
+ruteador.use(RUTAS.EMPLEADOS.BASE, rutasCrearGrupo);
+//RF19 - Actualizar Empleado - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF19
+ruteador.use(RUTAS.EMPLEADOS.BASE, rutasActualizarEmpleado);
+//RF24 - Actualizar Grupo de Empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF24
+ruteador.use(RUTAS.EMPLEADOS.BASE, rutasActualizarGrupo);
+//RF59 - Exportar Empleados- https://codeandco-wiki.netlify.app/docs/next/proyectos/textiles/documentacion/requisitos/RF59
+ruteador.use(RUTAS.EMPLEADOS.BASE, rutasExportarEmpleados);
+//RF16 - Crear Empleado - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF16
+ruteador.use(RUTAS.EMPLEADOS.BASE, rutasCrearEmpleado);
+module.exports = ruteador;
diff --git a/Eventos/Controladores/consultarEvento.controller.js b/Eventos/Controladores/consultarEvento.controller.js
new file mode 100644
index 00000000..b7503273
--- /dev/null
+++ b/Eventos/Controladores/consultarEvento.controller.js
@@ -0,0 +1,44 @@
+const repositorio = require('@altertex/eve/repos/repositorioConsultarEvento');
+const MENSAJES_EVENTOS = require('@altertex/util/const/mensajesEventos');
+
+/**
+ * Lee los detalles de un evento desde la base de datos utilizando su ID.
+ *
+ * Valida el parámetro `idEvento` y obtiene la información del evento a través del repositorio.
+ * Si el evento no es encontrado o el parámetro es inválido, retorna un error.
+ *
+ * @param {Express.Request} req - La solicitud HTTP que contiene el `idEvento` en el cuerpo.
+ * @param {Express.Response} res - La respuesta HTTP para enviar el resultado al cliente.
+ * @returns {Promise} Responde con el evento encontrado o un mensaje de error.
+ *
+ * @see [RF38 Leer evento](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF38)
+ *
+ */
+exports.consultarEvento = async (req, res) => {
+ const idEvento = parseInt(req.body.idEvento);
+
+ if (isNaN(idEvento)) {
+ return res
+ .status(MENSAJES_EVENTOS.PARAMETROS_INVALIDOS.codigo)
+ .json({ mensaje: MENSAJES_EVENTOS.PARAMETROS_INVALIDOS.mensaje });
+ }
+
+ try {
+ const evento = await repositorio.obtenerEventoPorId(idEvento);
+
+ if (!evento) {
+ return res
+ .status(MENSAJES_EVENTOS.EVENTO_NO_ENCONTRADO.codigo)
+ .json({ mensaje: MENSAJES_EVENTOS.EVENTO_NO_ENCONTRADO.mensaje });
+ }
+
+ return res.status(MENSAJES_EVENTOS.EVENTO_OBTENIDO.codigo).json({
+ mensaje: MENSAJES_EVENTOS.EVENTO_OBTENIDO.mensaje,
+ evento,
+ });
+ } catch {
+ return res
+ .status(MENSAJES_EVENTOS.ERROR_OBTENER_EVENTO.codigo)
+ .json({ mensaje: MENSAJES_EVENTOS.ERROR_OBTENER_EVENTO.mensaje });
+ }
+};
diff --git a/Eventos/Controladores/consultarListaEventos.controller.js b/Eventos/Controladores/consultarListaEventos.controller.js
new file mode 100644
index 00000000..47f4d247
--- /dev/null
+++ b/Eventos/Controladores/consultarListaEventos.controller.js
@@ -0,0 +1,40 @@
+//RF37 Consulta Lista de Eventos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF37]
+
+const repositorio = require('@altertex/eve/repos/repositorioConsultarListaEventos');
+const MENSAJES_EVENTOS = require('@altertex/util/const/mensajesEventos');
+
+/**
+ * Obtiene la lista de eventos asociados al cliente del usuario autenticado
+ * @function consultarListaEventos
+ * @param {object} req - Objeto de solicitud Express
+ * @param {object} res - Objeto de respuesta Express
+ * @returns {object} Respuesta JSON con la lista de eventos o mensaje de error
+ */
+exports.consultarListaEventos = async (req, res) => {
+ try {
+ const idCliente = parseInt(req.user.clienteSeleccionado);
+
+ if (isNaN(idCliente)) {
+ return res.status(MENSAJES_EVENTOS.PARAMETROS_INVALIDOS.codigo).json({
+ mensaje: 'ID del cliente no válido o no seleccionado',
+ });
+ }
+
+ const resultados = await repositorio.consultarListaEventos(idCliente);
+
+ if (!resultados || resultados.length === 0) {
+ return res.status(MENSAJES_EVENTOS.EVENTOS_NO_ENCONTRADOS.codigo).json({
+ mensaje: MENSAJES_EVENTOS.EVENTOS_NO_ENCONTRADOS.mensaje,
+ });
+ }
+
+ return res.status(MENSAJES_EVENTOS.LISTA_EVENTOS_OBTENIDA.codigo).json({
+ mensaje: MENSAJES_EVENTOS.LISTA_EVENTOS_OBTENIDA.mensaje,
+ listaEventos: resultados,
+ });
+ } catch {
+ return res
+ .status(MENSAJES_EVENTOS.ERROR_OBTENER_EVENTOS.codigo)
+ .json({ mensaje: MENSAJES_EVENTOS.ERROR_OBTENER_EVENTOS.mensaje });
+ }
+};
diff --git a/Eventos/Controladores/crearEvento.controller.js b/Eventos/Controladores/crearEvento.controller.js
new file mode 100644
index 00000000..fa769be6
--- /dev/null
+++ b/Eventos/Controladores/crearEvento.controller.js
@@ -0,0 +1,74 @@
+// RF36 - Crear Evento - [https://codeandco-wiki.netlify.app/docs/next/proyectos/textiles/documentacion/requisitos/RF36]
+
+const repositorio = require('@altertex/eve/repos/repositorioCrearEvento');
+const MENSAJES_EVENTOS = require('@altertex/util/const/mensajesEventos');
+
+/**
+ * Controlador para crear un nuevo evento.
+ *
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.body - Cuerpo de la solicitud que contiene los datos del evento.
+ * @param {string} req.body.idCliente - ID del cliente asociado al evento.
+ * @param {string} req.body.nombre - Nombre del evento.
+ * @param {string} req.body.descripcion - Descripción del evento.
+ * @param {number} req.body.puntos - Puntos otorgados por el evento.
+ * @param {number} req.body.multiplicador - Multiplicador de puntos del evento.
+ * @param {string} req.body.periodoRenovacion - Periodo de renovación del evento.
+ * @param {boolean} req.body.renovacion - Indica si el evento se renueva automáticamente.
+ * @param {object} res - Objeto de respuesta de Express.
+ *
+ * @returns {object} - Respuesta JSON con el resultado de la operación.
+ */
+exports.crearEvento = async (req, res) => {
+ try {
+ const { idCliente, nombre, descripcion, puntos, multiplicador, periodoRenovacion, renovacion } = req.body;
+
+ // Validaciones básicas de campos requeridos (descripcion y periodoRenovacion son opcionales)
+ if (!idCliente || !nombre || !puntos || !multiplicador) {
+
+ return res.status(MENSAJES_EVENTOS.PARAMETROS_INVALIDOS.codigo).json({
+ codigo: MENSAJES_EVENTOS.PARAMETROS_INVALIDOS.codigo,
+ mensaje: MENSAJES_EVENTOS.PARAMETROS_INVALIDOS.mensaje,
+ });
+ }
+
+ // Validar los datos de entrada
+ const idClienteNum = parseInt(idCliente, 10);
+ const puntosNum = parseFloat(puntos);
+ const multiplicadorNum = parseFloat(multiplicador);
+
+ // Validaciones de formato
+ if (isNaN(idClienteNum) || idClienteNum <= 0) {
+ return res.status(MENSAJES_EVENTOS.PARAMETROS_INVALIDOS.codigo).json({
+ codigo: MENSAJES_EVENTOS.PARAMETROS_INVALIDOS.codigo,
+ mensaje: 'El ID del cliente debe ser un número válido mayor a 0.',
+ });
+ }
+
+ const nuevoEvento = {
+ idCliente: idClienteNum,
+ nombre,
+ descripcion: descripcion && descripcion.trim() !== '' ? descripcion : null,
+ puntos: puntosNum,
+ multiplicador: multiplicadorNum,
+ periodoRenovacion: periodoRenovacion && periodoRenovacion.trim() !== '' ? periodoRenovacion : null,
+ renovacion: renovacion ? 1 : 0,
+ };
+
+ const resultado = await repositorio.crearEvento(nuevoEvento);
+
+ // Verificar si el evento fue creado exitosamente
+ return res.status(MENSAJES_EVENTOS.EVENTO_CREADO.codigo).json({
+ codigo: MENSAJES_EVENTOS.EVENTO_CREADO.codigo,
+ mensaje: MENSAJES_EVENTOS.EVENTO_CREADO.mensaje,
+ evento: resultado?.evento || resultado,
+ });
+
+ } catch (error) {
+ // Usar el mensaje personalizado del error en la respuesta
+ return res.status(MENSAJES_EVENTOS.ERROR_CREAR_EVENTO.codigo).json({
+ codigo: MENSAJES_EVENTOS.ERROR_CREAR_EVENTO.codigo,
+ mensaje: error.message || MENSAJES_EVENTOS.ERROR_CREAR_EVENTO.mensaje,
+ });
+ }
+};
diff --git a/Eventos/Controladores/eliminarEvento.controller.js b/Eventos/Controladores/eliminarEvento.controller.js
new file mode 100644
index 00000000..9f869ca0
--- /dev/null
+++ b/Eventos/Controladores/eliminarEvento.controller.js
@@ -0,0 +1,52 @@
+//RF40 Eliminar Evento - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF40]
+const repositorio = require('@altertex/eve/repos/repositorioEliminarEvento');
+const MENSAJES_EVENTOS = require('@altertex/util/const/mensajesEventos');
+
+/**
+ * Elimina un evento específico para un cliente
+ * @function eliminarEvento
+ * @param {object} req - Objeto de solicitud Express
+ * @param {object} res - Objeto de respuesta Express
+ * @returns {object} Respuesta JSON con confirmación o mensaje de error
+ */
+exports.eliminarEvento = async (req, res) => {
+ try {
+ const idsEvento = req.body.idsEvento;
+
+ if (!Array.isArray(idsEvento) || idsEvento.length === 0) {
+ return res.status(MENSAJES_EVENTOS.EVENTO_NO_ENCONTRADO.codigo).json({
+ mensaje: MENSAJES_EVENTOS.EVENTO_NO_ENCONTRADO.mensaje,
+ });
+ }
+
+ let eliminados = 0;
+ const noEncontrados = [];
+
+ await Promise.all(
+ idsEvento.map(async (idEvento) => {
+ const resultadoEvento = await repositorio.eliminarEvento(idEvento);
+ if (resultadoEvento.affectedRows === 0) {
+ noEncontrados.push(idEvento);
+ } else {
+ eliminados += 1;
+ }
+ })
+ );
+
+ if (eliminados === 0) {
+ return res.status(MENSAJES_EVENTOS.EVENTO_NO_ENCONTRADO.codigo).json({
+ mensaje: MENSAJES_EVENTOS.EVENTO_NO_ENCONTRADO.mensaje,
+ noEncontrados,
+ });
+ }
+
+ return res.status(MENSAJES_EVENTOS.EVENTO_ELIMINADO.codigo).json({
+ mensaje: MENSAJES_EVENTOS.EVENTO_ELIMINADO.mensaje,
+ noEncontrados: noEncontrados.length ? noEncontrados : undefined,
+ });
+ } catch {
+ return res.status(MENSAJES_EVENTOS.ERROR_ELIMINAR_EVENTO.codigo).json({
+ mensaje: MENSAJES_EVENTOS.ERROR_ELIMINAR_EVENTO.mensaje,
+ });
+ }
+};
diff --git a/Eventos/Datos/Repositorios/repositorioConsultarEvento.js b/Eventos/Datos/Repositorios/repositorioConsultarEvento.js
new file mode 100644
index 00000000..a72c8c4f
--- /dev/null
+++ b/Eventos/Datos/Repositorios/repositorioConsultarEvento.js
@@ -0,0 +1,33 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_EVENTOS = require('@altertex/util/const/consultasEventos');
+
+/**
+ * Obtiene un evento desde la base de datos mediante su ID.
+ *
+ * Ejecuta una consulta SQL y retorna el primer evento encontrado o `null` si no existe.
+ *
+ * @param {number|string} idEvento - ID del evento a buscar.
+ * @returns {Promise} El evento encontrado o `null` si no existe.
+ * @throws {Error} Si ocurre un error al ejecutar la consulta.
+ *
+ * @see [RF38 Leer evento](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF38)
+ */
+exports.obtenerEventoPorId = async (idEvento) => {
+ const query = CONSULTAS_EVENTOS.LEER_EVENTO;
+
+ const resultado = await correrQuery(query, [idEvento]);
+
+ if (resultado.length === 0) return null;
+
+ const evento = {
+ idEvento: resultado[0].idEvento,
+ nombre: resultado[0].nombre,
+ descripcion: resultado[0].descripcion,
+ puntos: resultado[0].puntos,
+ multiplicador: resultado[0].multiplicador,
+ periodoRenovacion: resultado[0].periodoRenovacion,
+ renovacion: resultado[0].renovacion,
+ };
+
+ return evento;
+};
diff --git a/Eventos/Datos/Repositorios/repositorioConsultarListaEventos.js b/Eventos/Datos/Repositorios/repositorioConsultarListaEventos.js
new file mode 100644
index 00000000..65dd961f
--- /dev/null
+++ b/Eventos/Datos/Repositorios/repositorioConsultarListaEventos.js
@@ -0,0 +1,20 @@
+//RF37 Consulta Lista de Eventos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF37]
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_EVENTOS = require('@altertex/util/const/consultasEventos');
+
+/**
+ * Obtiene la lista de eventos de un cliente específico de la base de datos
+ * @function consultarListaEventos
+ * @param {number} clienteSeleccionado - ID del cliente seleccionado
+ * @returns {Array} - Lista de eventos encontrados
+ */
+exports.consultarListaEventos = async (clienteSeleccionado) => {
+ const query = CONSULTAS_EVENTOS.OBTENER_LISTA_EVENTOS;
+
+ try {
+ const listaEventos = await correrQuery(query, [clienteSeleccionado]);
+ return listaEventos;
+ } catch {
+ throw new Error('Error obteniendo la lista de eventos.');
+ }
+};
diff --git a/Eventos/Datos/Repositorios/repositorioCrearEvento.js b/Eventos/Datos/Repositorios/repositorioCrearEvento.js
new file mode 100644
index 00000000..55d09b47
--- /dev/null
+++ b/Eventos/Datos/Repositorios/repositorioCrearEvento.js
@@ -0,0 +1,64 @@
+// RF36 - Crear Evento - [https://codeandco-wiki.netlify.app/docs/next/proyectos/textiles/documentacion/requisitos/RF36]
+
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_EVENTOS = require('@altertex/util/const/consultasEventos');
+const MENSAJES_EVENTOS = require('@altertex/util/const/mensajesEventos');
+
+/**
+ * Crea un nuevo evento en la base de datos
+ * @function crearEvento
+ * @param {object} evento - Objeto que contiene los datos del evento a crear
+ * @param {number} evento.idCliente - ID del cliente asociado al evento
+ * @param {string} evento.nombre - Nombre del evento
+ * @param {string} evento.descripcion - Descripción del evento
+ * @param {number} evento.puntos - Puntos asociados al evento
+ * @param {number} evento.multiplicador - Multiplicador del evento
+ * @param {number} evento.periodoRenovacion - Periodo de renovación del evento
+ * @param {number} evento.renovacion - Renovación del evento
+ * @returns {object} - Resultado de la operación de creación
+ * @throws {Error} - Error personalizado según el problema encontrado
+ */
+exports.crearEvento = async ({
+ idCliente,
+ nombre,
+ descripcion,
+ puntos,
+ multiplicador,
+ periodoRenovacion,
+ renovacion,
+}) => {
+ try {
+ const query = CONSULTAS_EVENTOS.CREAR_EVENTO;
+
+ const resultado = await correrQuery(query, [
+ idCliente,
+ nombre,
+ descripcion,
+ puntos,
+ multiplicador,
+ periodoRenovacion,
+ renovacion,
+ ]);
+
+ // Si no hay resultado
+ if (!resultado) {
+ throw new Error(MENSAJES_EVENTOS.ERROR_INESPERADO.mensaje);
+ }
+
+ return resultado;
+ } catch (error) {
+ // Si es un error que ya hemos generado, lo lanzamos tal cual
+ const mensajesError = Object.values(MENSAJES_EVENTOS).map(msg => msg.mensaje);
+ if (mensajesError.includes(error.message)) {
+ throw error;
+ }
+
+ // Interpretamos posibles errores SQL - solo nos interesa si el cliente no existe
+ if (error.message.includes('foreign key constraint') || error.message.includes('FOREIGN KEY')) {
+ throw new Error(MENSAJES_EVENTOS.ERROR_CLIENTE_NO_EXISTE.mensaje);
+ }
+
+ // Si es otro tipo de error, lanzamos un error genérico
+ throw new Error(`${MENSAJES_EVENTOS.ERROR_INESPERADO.mensaje}: ${error.message}`);
+ }
+};
diff --git a/Eventos/Datos/Repositorios/repositorioEliminarEvento.js b/Eventos/Datos/Repositorios/repositorioEliminarEvento.js
new file mode 100644
index 00000000..fa63140d
--- /dev/null
+++ b/Eventos/Datos/Repositorios/repositorioEliminarEvento.js
@@ -0,0 +1,40 @@
+//RF40 Eliminar Evento - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF40]
+const db = require('@altertex/util/bd/db');
+const CONSULTAS_EVENTOS = require('@altertex/util/const/consultasEventos');
+
+/**
+ * Elimina un evento específico de la base de datos
+ * @function eliminarEvento
+ * @param {number} idEvento - ID del evento a eliminar
+ * @returns {object} - Resultado de la operación de eliminación
+ */
+exports.eliminarEvento = async (idEvento) => {
+ const conexion = await db.getConnection();
+
+ try {
+ await conexion.beginTransaction();
+
+ const [resultadosEmpleadosEventos] = await conexion.query(
+ CONSULTAS_EVENTOS.ELIMINAR_EMPLEADO_EVENTO,
+ [idEvento]
+ );
+
+ const [resultadosEventos] = await conexion.query(
+ CONSULTAS_EVENTOS.ELIMINAR_EVENTO,
+ [idEvento]
+ );
+
+ await conexion.commit();
+
+ return {
+ affectedRows: resultadosEventos.affectedRows,
+ resultadosEventos,
+ resultadosEmpleadosEventos,
+ };
+ } catch {
+ await conexion.rollback();
+ throw new Error('Error eliminando evento');
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
\ No newline at end of file
diff --git a/Eventos/Rutas/RutasIndividuales/consultarEvento.routes.js b/Eventos/Rutas/RutasIndividuales/consultarEvento.routes.js
new file mode 100644
index 00000000..94653d09
--- /dev/null
+++ b/Eventos/Rutas/RutasIndividuales/consultarEvento.routes.js
@@ -0,0 +1,103 @@
+// RF38 - Leer Evento - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF38]
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/eve/ctrl/consultarEvento.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/eventos/consultar-evento:
+ * post:
+ * summary: Muestra la información de un evento específico.
+ * description: Obtiene los detalles completos de un evento usando su ID.
+ * tags: [Eventos]
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * required:
+ * - idEvento
+ * properties:
+ * idEvento:
+ * type: integer
+ * example: 123
+ * description: Identificador único del evento
+ * responses:
+ * 200:
+ * description: Evento encontrado exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Información del evento obtenida exitosamente."
+ * evento:
+ * type: object
+ * properties:
+ * idEvento:
+ * type: integer
+ * example: 123
+ * nombre:
+ * type: string
+ * example: "Entrega Puntual"
+ * descripcion:
+ * type: string
+ * example: "Se otorgan puntos por cumplir con los tiempos de entrega en producción."
+ * puntos:
+ * type: integer
+ * example: 10
+ * multiplicador:
+ * type: number
+ * example: 1.5
+ * periodoRenovacion:
+ * type: string
+ * example: "Mensual"
+ * renovacion:
+ * type: boolean
+ * example: true
+ * 404:
+ * description: Evento no encontrado.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Evento no encontrado."
+ * 500:
+ * description: Error interno del servidor al leer el evento.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Ocurrió un error al leer el evento."
+ */
+ruteador.post(
+ RUTAS.EVENTOS.CONSULTAR_EVENTO,
+ validarYSanitizar,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.LEER_EVENTO),
+ controlador.consultarEvento
+);
+
+module.exports = ruteador;
diff --git a/Eventos/Rutas/RutasIndividuales/consultarListaEventos.routes.js b/Eventos/Rutas/RutasIndividuales/consultarListaEventos.routes.js
new file mode 100644
index 00000000..40f767c2
--- /dev/null
+++ b/Eventos/Rutas/RutasIndividuales/consultarListaEventos.routes.js
@@ -0,0 +1,71 @@
+//RF37 Consulta Lista de Eventos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF37]
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/eve/ctrl/consultarListaEventos.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/eventos/consultar-lista-eventos:
+ * post:
+ * summary: Obtener lista de eventos
+ * tags: [Eventos]
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * responses:
+ * 200:
+ * description: Lista de eventos obtenida exitosamente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Lista de eventos obtenida exitosamente
+ * lista_eventos:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * idEvento:
+ * type: integer
+ * nombre:
+ * type: string
+ * descripcion:
+ * type: string
+ * puntos:
+ * type: number
+ * periodoRenovacion:
+ * type: string
+ * renovacion:
+ * type: boolean
+ * 204:
+ * description: No se encontraron eventos
+ * 400:
+ * description: Parámetros inválidos
+ * 401:
+ * description: No autorizado
+ * 403:
+ * description: Acceso denegado
+ * 500:
+ * description: Error al obtener eventos
+ */
+ruteador.post(
+ RUTAS.EVENTOS.CONSULTAR_LISTA_EVENTOS,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CONSULTAR_EVENTO),
+ controlador.consultarListaEventos
+);
+
+module.exports = ruteador;
diff --git a/Eventos/Rutas/RutasIndividuales/crearEvento.routes.js b/Eventos/Rutas/RutasIndividuales/crearEvento.routes.js
new file mode 100644
index 00000000..97feadf0
--- /dev/null
+++ b/Eventos/Rutas/RutasIndividuales/crearEvento.routes.js
@@ -0,0 +1,85 @@
+// RF36 - Crear Evento - [https://codeandco-wiki.netlify.app/docs/next/proyectos/textiles/documentacion/requisitos/RF36]
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/eve/ctrl/crearEvento.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/eventos/crear:
+ * post:
+ * summary: Crea un nuevo evento.
+ * description: Este endpoint permite crear un nuevo evento en el sistema.
+ * tags: [Eventos]
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * idCliente:
+ * type: string
+ * description: ID del cliente asociado al evento.
+ * example: 101
+ * nombre:
+ * type: string
+ * description: Nombre del evento.
+ * example: Evento de prueba
+ * descripcion:
+ * type: string
+ * description: Descripción del evento.
+ * example: Este es un evento de prueba.
+ * puntos:
+ * type: number
+ * format: double
+ * description: Puntos otorgados por el evento.
+ * example: 10.5
+ * multiplicador:
+ * type: number
+ * format: double
+ * description: Multiplicador de puntos del evento.
+ * example: 1.5
+ * periodoRenovacion:
+ * type: string
+ * description: Periodo de renovación del evento.
+ * example: mensual
+ * renovacion:
+ * type: boolean
+ * description: Indica si el evento se renueva automáticamente.
+ * example: true
+ * responses:
+ * 200:
+ * description: Evento creado exitosamente.
+ * 400:
+ * description: Solicitud incorrecta.
+ * 401:
+ * description: No autorizado.
+ * 403:
+ * description: Prohibido.
+ * 404:
+ * description: No encontrado.
+ * 500:
+ * description: Error interno del servidor.
+ */
+ruteador.post(
+ RUTAS.EVENTOS.CREAR,
+ validarYSanitizar,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CREAR_EVENTO),
+ controlador.crearEvento
+);
+
+module.exports = ruteador;
diff --git a/Eventos/Rutas/RutasIndividuales/eliminarEvento.routes.js b/Eventos/Rutas/RutasIndividuales/eliminarEvento.routes.js
new file mode 100644
index 00000000..b536f7e4
--- /dev/null
+++ b/Eventos/Rutas/RutasIndividuales/eliminarEvento.routes.js
@@ -0,0 +1,64 @@
+//RF40 Eliminar Evento - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF40]
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/eve/ctrl/eliminarEvento.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/eventos/eliminar:
+ * delete:
+ * summary: Eliminar un evento
+ * tags: [Eventos]
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * idEvento:
+ * type: integer
+ * description: ID del evento a eliminar
+ * responses:
+ * 200:
+ * description: Evento eliminado exitosamente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Evento eliminado exitosamente
+ * 400:
+ * description: Parámetros inválidos
+ * 401:
+ * description: No autorizado
+ * 403:
+ * description: Acceso denegado
+ * 404:
+ * description: Evento no encontrado
+ * 500:
+ * description: Error al eliminar el evento
+ */
+ruteador.post(
+ RUTAS.EVENTOS.ELIMINAR,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.ELIMINAR_EVENTO),
+ controlador.eliminarEvento
+);
+
+module.exports = ruteador;
diff --git a/Eventos/Rutas/indexEventos.routes.js b/Eventos/Rutas/indexEventos.routes.js
new file mode 100644
index 00000000..e3aef2a4
--- /dev/null
+++ b/Eventos/Rutas/indexEventos.routes.js
@@ -0,0 +1,20 @@
+const express = require('express');
+const ruteador = express.Router();
+const crearEvento = require('@altertex/eve/rutasInd/crearEvento.routes');
+const rutasConsultarListaEventos = require('@altertex/eve/rutasInd/consultarListaEventos.routes');
+const rutasConsultarEvento = require('@altertex/eve/rutasInd/consultarEvento.routes');
+const rutasEliminarEvento = require('@altertex/eve/rutasInd/eliminarEvento.routes');
+/**
+ * @module Eventos/Rutas
+ * @description Gestor de rutas para el módulo de eventos
+ */
+
+const RUTAS = require('@altertex/util/const/rutas');
+
+// Configuración de las rutas específicas para eventos
+ruteador.use(RUTAS.EVENTOS.BASE, crearEvento);
+ruteador.use(RUTAS.EVENTOS.BASE, rutasConsultarListaEventos);
+ruteador.use(RUTAS.EVENTOS.BASE, rutasEliminarEvento);
+ruteador.use(RUTAS.EVENTOS.BASE, rutasConsultarEvento);
+
+module.exports = ruteador;
diff --git a/Pagos/Controladores/actualizarTipoPago.controller.js b/Pagos/Controladores/actualizarTipoPago.controller.js
new file mode 100644
index 00000000..411c1718
--- /dev/null
+++ b/Pagos/Controladores/actualizarTipoPago.controller.js
@@ -0,0 +1,39 @@
+const MENSAJES = require('@altertex/util/const/mensajesPagos');
+const repositorio = require('@altertex/pago/repos/repositorioActualizarTipoPago');
+
+//RF[54] Actualizar lista de pago - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF54]
+
+/**
+ * Controlador para actualizar los tipos de pago disponibles.
+ *
+ * Este endpoint recibe un objeto con los cambios a realizar sobre los métodos de pago
+ * y utiliza el repositorio correspondiente para aplicar las actualizaciones en la base de datos.
+ *
+ * @function actualizarTipoPago
+ * @async
+ * @param {Express.Request} req - Objeto de solicitud HTTP de Express.
+ * @param {object} req.body - Cuerpo de la solicitud.
+ * @param {Array} req.body.cambios - Lista de métodos de pago a actualizar, incluyendo su nuevo estado.
+ * @param {Express.Response} res - Objeto de respuesta HTTP de Express.
+ * @returns {Promise} Retorna una respuesta JSON indicando éxito o error en la operación.
+ */
+exports.actualizarTipoPago = async (req, res) => {
+ const datos = req.body.cambios;
+
+ if (!datos) {
+ return res
+ .status(MENSAJES.ERROR_ACTUALIZAR.codigo)
+ .json({ mensaje: MENSAJES.ERROR_ACTUALIZAR.mensaje });
+ }
+
+ try {
+ await repositorio.actualizarTipoPago(datos);
+ return res
+ .status(MENSAJES.EXITO_ACTUALIZAR.codigo)
+ .json({ mensaje: MENSAJES.EXITO_ACTUALIZAR.mensaje, datos });
+ } catch {
+ return res
+ .status(MENSAJES.ERROR_ACTUALIZAR.codigo)
+ .json({ mensaje: MENSAJES.ERROR_ACTUALIZAR.mensaje });
+ }
+};
diff --git a/Pagos/Controladores/consultarTipoPago.controller.js b/Pagos/Controladores/consultarTipoPago.controller.js
new file mode 100644
index 00000000..d5a0d1a6
--- /dev/null
+++ b/Pagos/Controladores/consultarTipoPago.controller.js
@@ -0,0 +1,36 @@
+const MENSAJES = require('@altertex/util/const/mensajesPagos');
+const repositorio = require('@altertex/pago/repos/repositorioConsultarTipoPago');
+
+//RF[52] Consulta Lista de Pago - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF52]
+
+/**
+ * Controlador para consultar los tipos de pago disponibles para el cliente autenticado.
+ *
+ * Este endpoint obtiene el ID del cliente desde el usuario autenticado (`req.user.clienteSeleccionado`)
+ * y devuelve la lista de métodos de pago habilitados para dicho cliente.
+ *
+ * @function consultarTipoPago
+ * @async
+ * @param {Express.Request} req - Objeto de solicitud HTTP. Se espera que contenga `user.clienteSeleccionado`.
+ * @param {Express.Response} res - Objeto de respuesta HTTP.
+ * @returns {Promise} Retorna una respuesta JSON con la lista de métodos de pago o un mensaje de error.
+ */
+exports.consultarTipoPago = async (req, res) => {
+ const cliente = req.user.clienteSeleccionado;
+ if (!cliente) {
+ return res
+ .status(MENSAJES.ERROR_CLIENTE_SELECCIONADO.codigo)
+ .json({ mensaje: MENSAJES.ERROR_CLIENTE_SELECCIONADO.mensaje });
+ }
+ try {
+ const listaTipoPagos = await repositorio.consutlarTipoPago(cliente);
+
+ return res
+ .status(MENSAJES.CONSULTA_EXITOSA.codigo)
+ .json({ mensaje: MENSAJES.CONSULTA_EXITOSA.mensaje, listaTipoPagos });
+ } catch {
+ return res
+ .status(MENSAJES.ERROR_CONSULTA.codigo)
+ .json({ mensaje: MENSAJES.ERROR_CONSULTA.mensaje });
+ }
+};
diff --git a/Pagos/Datos/Repositorios/repositorioActualizarTipoPago.js b/Pagos/Datos/Repositorios/repositorioActualizarTipoPago.js
new file mode 100644
index 00000000..5417a136
--- /dev/null
+++ b/Pagos/Datos/Repositorios/repositorioActualizarTipoPago.js
@@ -0,0 +1,33 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const MENSAJES = require('@altertex/util/const/mensajesPagos');
+const CONSULTAS = require('@altertex/util/const/consultasPagos');
+
+//RF[54] Actualizar Lista de Pago - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF54]
+
+/**
+ * Repositorio para actualizar el estado de los tipos de pago en la base de datos.
+ *
+ * Recorre un arreglo de objetos que contienen la información de cada método de pago
+ * (ID, nombre del método y si está habilitado o no), y ejecuta la consulta SQL correspondiente
+ * para actualizar su estado.
+ *
+ * @function actualizarTipoPago
+ * @async
+ * @param {Array<{ id: number, metodo: string, habilitado: boolean }>} datos - Lista de métodos de pago a actualizar.
+ * @throws {Error} Si el arreglo está vacío o si ocurre un error en la base de datos.
+ * @returns {Promise} Promesa que se resuelve cuando todas las actualizaciones han sido ejecutadas.
+ */
+exports.actualizarTipoPago = async (datos) => {
+ if (!Array.isArray(datos) || datos.length === 0) {
+ throw new Error('No hay datos para actualizar.');
+ }
+ try {
+ await Promise.all(
+ datos.map(({ id, habilitado }) => {
+ return correrQuery(CONSULTAS.ACTUALIZAR, [habilitado, id]);
+ })
+ );
+ } catch {
+ throw new Error(MENSAJES.ERROR_ACTUALIZAR.mensaje);
+ }
+};
diff --git a/Pagos/Datos/Repositorios/repositorioConsultarTipoPago.js b/Pagos/Datos/Repositorios/repositorioConsultarTipoPago.js
new file mode 100644
index 00000000..cd9e9839
--- /dev/null
+++ b/Pagos/Datos/Repositorios/repositorioConsultarTipoPago.js
@@ -0,0 +1,28 @@
+const MENSAJES = require('@altertex/util/const/mensajesPagos');
+const CONSULTAS = require('@altertex/util/const/consultasPagos');
+const correrQuery = require('@altertex/util/ser/correrQuery');
+
+//RF[52] Consulta Lista de Pago - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF52]
+
+/**
+ * Repositorio para consultar la lista de métodos de pago habilitados para un cliente.
+ *
+ * Ejecuta una consulta SQL que devuelve los tipos de pago disponibles para el cliente especificado.
+ *
+ * @function consutlarTipoPago
+ * @async
+ * @param {number|string} cliente - Identificador del cliente cuyos métodos de pago se desean consultar.
+ * @throws {Error} Si no se proporciona un cliente o si ocurre un error durante la consulta.
+ * @returns {Promise>} Promesa que resuelve con un arreglo de objetos que representan los métodos de pago.
+ */
+exports.consutlarTipoPago = async (cliente) => {
+ if (!cliente) {
+ throw new Error(MENSAJES.ERROR_CONSULTA.mensaje);
+ }
+ try {
+ const listaTipoPagos = await correrQuery(CONSULTAS.CONSULTAR_LISTA, [cliente]);
+ return listaTipoPagos;
+ } catch {
+ throw new Error(MENSAJES.ERROR_CONSULTA.mensaje);
+ }
+};
diff --git a/Pagos/Rutas/RutasIndividuales/actualizarTipoPago.routes.js b/Pagos/Rutas/RutasIndividuales/actualizarTipoPago.routes.js
new file mode 100644
index 00000000..b3db590d
--- /dev/null
+++ b/Pagos/Rutas/RutasIndividuales/actualizarTipoPago.routes.js
@@ -0,0 +1,104 @@
+const express = require('express');
+const ruteador = express.Router();
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+const controlador = require('@altertex/pago/ctrl/actualizarTipoPago.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const revisarPermisos = require('@altertex/util/inter/verificarPermisos');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+//RF[54] Actualizar Lista de Pago - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF54]
+
+/**
+ * @swagger
+ * /api/pagos/actualizar:
+ * put:
+ * summary: Actualiza el estado de métodos de pago habilitados.
+ * tags:
+ * - Pagos
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * cambios:
+ * type: array
+ * description: Lista de tipos de pago a actualizar.
+ * items:
+ * type: object
+ * required:
+ * - id
+ * - metodo
+ * - habilitado
+ * properties:
+ * id:
+ * type: integer
+ * example: 1
+ * metodo:
+ * type: string
+ * example: "tarjeta_credito"
+ * habilitado:
+ * type: boolean
+ * example: true
+ * responses:
+ * 200:
+ * description: Tipos de pago actualizados correctamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Método(s) de pago actualizados correctamente."
+ * datos:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * id:
+ * type: integer
+ * metodo:
+ * type: string
+ * habilitado:
+ * type: boolean
+ * 400:
+ * description: Error en los datos enviados o en la actualización.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Error al actualizar los métodos de pago."
+ * x-codeSamples:
+ * - lang: JavaScript
+ * label: cURL
+ * source: |
+ * curl -X PUT "https://tu-api.com/api/pagos/tipo" \
+ * -H "x-api-key: TU_API_KEY" \
+ * -H "Authorization: Bearer TU_TOKEN" \
+ * -H "Content-Type: application/json" \
+ * -d '{"cambios":[{"id":1,"metodo":"tarjeta_credito","habilitado":true}]}'
+ */
+ruteador.put(
+ RUTAS.PAGOS.ACTUALIZAR,
+ revisarApiKey(),
+ validarYSanitizar,
+ autorizarToken,
+ limitePeticionesDiarias,
+ revisarPermisos(PERMISOS.ACTUALIZAR_TIPO_PAGO),
+ controlador.actualizarTipoPago
+);
+
+module.exports = ruteador;
diff --git a/Pagos/Rutas/RutasIndividuales/consultarTipoPago.routes.js b/Pagos/Rutas/RutasIndividuales/consultarTipoPago.routes.js
new file mode 100644
index 00000000..409757d8
--- /dev/null
+++ b/Pagos/Rutas/RutasIndividuales/consultarTipoPago.routes.js
@@ -0,0 +1,80 @@
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/pago/ctrl/consultarTipoPago.controller');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const revisarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+//RF[52] Consulta Lista de Pago - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF52]
+
+/**
+ * @swagger
+ * /api/pagos/consultar-lista:
+ * get:
+ * summary: Consulta los tipos de pago disponibles para el cliente autenticado.
+ * tags:
+ * - Pagos
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * responses:
+ * 200:
+ * description: Consulta exitosa de métodos de pago.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Consulta exitosa."
+ * listaTipoPagos:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * id:
+ * type: integer
+ * example: 1
+ * metodo:
+ * type: string
+ * example: "tarjeta_credito"
+ * habilitado:
+ * type: boolean
+ * example: true
+ * 400:
+ * description: El cliente no ha sido seleccionado.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "No se ha seleccionado un cliente válido."
+ * 500:
+ * description: Error interno al consultar los métodos de pago.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Error al consultar los métodos de pago."
+ */
+ruteador.get(
+ RUTAS.PAGOS.CONSULTAR_LISTA,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ revisarPermisos(PERMISOS.CONSULTAR_TIPOS_PAGO),
+ controlador.consultarTipoPago
+);
+
+module.exports = ruteador;
diff --git a/Pagos/Rutas/indexPagos.routes.js b/Pagos/Rutas/indexPagos.routes.js
new file mode 100644
index 00000000..7282b5a4
--- /dev/null
+++ b/Pagos/Rutas/indexPagos.routes.js
@@ -0,0 +1,11 @@
+const express = require('express');
+const ruteador = express.Router();
+const RUTAS = require('@altertex/util/const/rutas');
+
+const rutaConsultarPago = require('@altertex/pago/rutas/rutasInd/consultarTipoPago.routes');
+const rutasActualizarPago = require('@altertex/pago/rutas/rutasInd/actualizarTipoPago.routes');
+
+ruteador.use(RUTAS.PAGOS.BASE, rutaConsultarPago);
+ruteador.use(RUTAS.PAGOS.BASE, rutasActualizarPago);
+
+module.exports = ruteador;
diff --git a/Pedidos/Controladores/actualizarPedido.controller.js b/Pedidos/Controladores/actualizarPedido.controller.js
new file mode 100644
index 00000000..299ddbd4
--- /dev/null
+++ b/Pedidos/Controladores/actualizarPedido.controller.js
@@ -0,0 +1,47 @@
+const MENSAJES = require('@altertex/util/const/mensajesPedidos');
+const repositorio = require('@altertex/pedidos/repos/repositorioActualizarPedido');
+
+/**
+ * RF[62] - Actualizar Pedido [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF62]
+ * Controlador para actualizar la información de uno o varios pedidos.
+ *
+ * Respuestas posibles:
+ * - 400 si faltan datos en el cuerpo de la solicitud.
+ * - 200 si el pedido se actualiza correctamente.
+ *
+ * @async
+ * @function actualizarGrupoEmpleados
+ * @param {Express.Request} req - Objeto de solicitud HTTP de Express.
+ * @param {Express.Response} res - Objeto de respuesta HTTP de Express.
+ * @returns {Promise} La respuesta HTTP con el estado y mensaje correspondiente.
+ */
+exports.actualizarPedido = async (req, res) => {
+ let datos;
+ if (req.body.idPedido) {
+ datos = [req.body];
+ } else if (req.body.cambios) {
+ datos = Array.isArray(req.body.cambios) ? req.body.cambios : [req.body.cambios];
+ } else {
+ return res.status(MENSAJES.ERROR_ACTUALIZAR_PEDIDO.codigo).json({
+ mensaje: MENSAJES.ERROR_ACTUALIZAR_PEDIDO.mensaje,
+ });
+ }
+
+ if (!datos || datos.length === 0) {
+ return res.status(MENSAJES.ERROR_ACTUALIZAR_PEDIDO.codigo).json({
+ mensaje: MENSAJES.ERROR_ACTUALIZAR_PEDIDO.mensaje,
+ });
+ }
+
+ try {
+ await repositorio.actualizarPedido(datos);
+ return res.status(MENSAJES.PEDIDO_ACTUALIZADO.codigo).json({
+ mensaje: MENSAJES.PEDIDO_ACTUALIZADO.mensaje,
+ datos,
+ });
+ } catch {
+ return res.status(MENSAJES.ERROR_ACTUALIZAR_PEDIDO.codigo).json({
+ mensaje: MENSAJES.ERROR_ACTUALIZAR_PEDIDO.mensaje,
+ });
+ }
+};
diff --git a/Pedidos/Controladores/eliminarPedidos.controller.js b/Pedidos/Controladores/eliminarPedidos.controller.js
new file mode 100644
index 00000000..bad39007
--- /dev/null
+++ b/Pedidos/Controladores/eliminarPedidos.controller.js
@@ -0,0 +1,52 @@
+const repositorio = require('@altertex/pedidos/repos/repositorioEliminarPedidos');
+const MENSAJES_PEDIDOS = require('@altertex/util/const/mensajesPedidos');
+
+/**
+ * Controlador para eliminar pedidos.
+ * RF[63] - Elimina pedido - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF63
+ *
+ * @async
+ * @function eliminarPedido
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.body - Cuerpo de la solicitud HTTP.
+ * @param {number[]} req.body.idsPedido - Array de IDs numéricos de los pedidos a eliminar.
+ * @param {object} res - Objeto de respuesta de Express.
+ * @returns {Promise} Respuesta HTTP con estado:
+ * - 200 si los pedidos fueron eliminados correctamente.
+ * - 404 si no se encontraron los pedidos.
+ * - 500 si ocurre un error en el servidor.
+ * @throws {Error} Si ocurre un error durante la eliminación.
+ */
+exports.eliminarPedido = async (req, res) => {
+ try {
+ const idsPedidos = req.body.idsPedido;
+
+ // Validar que se envíen IDs válidos
+ if (!Array.isArray(idsPedidos) || idsPedidos.length === 0) {
+ return res.status(MENSAJES_PEDIDOS.PEDIDO_NO_ENCONTRADO.codigo).json({
+ mensaje: MENSAJES_PEDIDOS.PEDIDO_NO_ENCONTRADO.mensaje,
+ });
+ }
+
+ // Usar transacciones para eliminar los pedidos
+ await Promise.all(
+ idsPedidos.map(async (idPedido) => {
+ const resultadoPedido = await repositorio.eliminarPedido(idPedido);
+
+ if (resultadoPedido.resultadoPedido.affectedRows === 0) {
+ throw new Error(`Pedido con ID ${idPedido} no encontrado`);
+ }
+ })
+ );
+
+ // Respuesta exitosa
+ return res.status(MENSAJES_PEDIDOS.PEDIDO_ELIMINADO.codigo).json({
+ mensaje: MENSAJES_PEDIDOS.PEDIDO_ELIMINADO.mensaje,
+ });
+ } catch {
+ // Respuesta de error
+ return res.status(MENSAJES_PEDIDOS.ERROR_ELIMINAR_PEDIDO.codigo).json({
+ mensaje: MENSAJES_PEDIDOS.ERROR_ELIMINAR_PEDIDO.mensaje,
+ });
+ }
+};
diff --git a/Pedidos/Controladores/obtenerPedidos.controller.js b/Pedidos/Controladores/obtenerPedidos.controller.js
new file mode 100644
index 00000000..41016834
--- /dev/null
+++ b/Pedidos/Controladores/obtenerPedidos.controller.js
@@ -0,0 +1,46 @@
+const MENSAJES = require('@altertex/util/const/mensajesPedidos');
+const repositorio = require('@altertex/pedidos/repos/repositorioObtenerPedidos');
+
+/**
+ * RF60 - Consulta Lista de Pedidos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF60
+ * Controlador para obtener la lista de pedidos de un cliente autenticado.
+ *
+ * @async
+ * @function obtenerLista
+ * @param {Express.Request} req - Objeto de solicitud de Express. Debe contener `user.clienteSeleccionado`.
+ * @param {Express.Response} res - Objeto de respuesta de Express.
+ * @returns {Promise} Respuesta HTTP con la lista de pedidos o un mensaje de error.
+ *
+ * @example
+ * // Éxito
+ * res.status(200).json({
+ * mensaje: 'Consulta exitosa',
+ * pedidos: [...]
+ * });
+ *
+ * @example
+ * // Error: cliente no seleccionado
+ * res.status(400).json({
+ * error: 'No se pudo consultar los pedidos.'
+ * });
+ */
+exports.obtenerLista = async (req, res) => {
+ const idCliente = req.user?.clienteSeleccionado;
+
+ if (!idCliente) {
+ return res
+ .status(MENSAJES.ERROR_CONSULTAR_PEDIDOS.codigo)
+ .json({ error: MENSAJES.ERROR_CONSULTAR_PEDIDOS.mensaje });
+ }
+
+ try {
+ const resultado = await repositorio.obteneLista(idCliente);
+ return res
+ .status(MENSAJES.CONSULTA_EXITOSA.codigo)
+ .json({ mensaje: MENSAJES.CONSULTA_EXITOSA.mensaje, pedidos: resultado });
+ } catch {
+ return res
+ .status(MENSAJES.ERROR_CONSULTAR_PEDIDOS.codigo)
+ .json({ error: MENSAJES.ERROR_CONSULTAR_PEDIDOS.mensaje });
+ }
+};
diff --git a/Pedidos/Datos/Repositorios/repositorioActualizarPedido.js b/Pedidos/Datos/Repositorios/repositorioActualizarPedido.js
new file mode 100644
index 00000000..002d898a
--- /dev/null
+++ b/Pedidos/Datos/Repositorios/repositorioActualizarPedido.js
@@ -0,0 +1,50 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const MENSAJES = require('@altertex/util/const/mensajesPedidos');
+const CONSULTAS = require('@altertex/util/const/consultasPedidos');
+
+//RF[62] - Actualizar Pedido - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF62]
+
+/**
+ * Actualiza uno o varios pedidos en la base de datos con nueva información
+ * de estado, precio total, ID de envío y ID de pago.
+ *
+ * Esta función realiza:
+ * - La validación de que se proporcionen datos para actualizar.
+ * - La actualización simultánea de múltiples pedidos usando Promise.all.
+ * - El manejo de errores durante el proceso de actualización.
+ *
+ * La función procesa cada pedido de forma paralela, actualizando sus campos
+ * mediante una consulta SQL preparada con los parámetros proporcionados.
+ *
+ * @async
+ * @function actualizarPedido
+ * @param {object[]} datos - Array de objetos con los datos de los pedidos a actualizar.
+ * @param {number} datos[].idPedido - ID único del pedido a actualizar.
+ * @param {string|number} datos[].estado - Nuevo estado del pedido.
+ * @param {number} datos[].precioTotal - Nuevo precio total del pedido.
+ * @param {number} datos[].idEnvio - ID del envío asociado al pedido.
+ * @param {number} datos[].idPago - ID del pago asociado al pedido.
+ * @throws {Error} 'Sin datos para actualizar.' - Si el array está vacío o no es válido.
+ * @throws {Error} Mensaje de error específico desde MENSAJES.ERROR_ACTUALIZAR_PEDIDO - Si ocurre algún error durante la actualización.
+ */
+exports.actualizarPedido = async (datos) => {
+ if (!Array.isArray(datos) || datos.length === 0) {
+ throw new Error('Sin datos para actualizar.');
+ }
+
+ try {
+ await Promise.all(
+ datos.map(({ idPedido, estado, precioTotal, idEnvio, idPago }) => {
+ return correrQuery(CONSULTAS.ACTUALIZAR_PEDIDO, [
+ estado,
+ precioTotal,
+ idPago,
+ idEnvio,
+ idPedido,
+ ]);
+ })
+ );
+ } catch {
+ throw new Error(MENSAJES.ERROR_ACTUALIZAR_PEDIDO.mensaje);
+ }
+};
diff --git a/Pedidos/Datos/Repositorios/repositorioEliminarPedidos.js b/Pedidos/Datos/Repositorios/repositorioEliminarPedidos.js
new file mode 100644
index 00000000..f6c14ae7
--- /dev/null
+++ b/Pedidos/Datos/Repositorios/repositorioEliminarPedidos.js
@@ -0,0 +1,56 @@
+const db = require('@altertex/util/bd/db');
+const CONSULTAS_PEDIDOS = require('@altertex/util/const/consultasPedidos');
+
+/**
+ * Elimina las opciones asociadas a un pedido.
+ * //RF[63] Elimina pedido - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF63]
+ * @async
+ * @function eliminarPedido
+ * @param {number} idPedido - ID del pedido a eliminar.
+ * @returns {Promise} Objeto de resultado de la operación MySQL (por ejemplo, `affectedRows`).
+ * @throws {Error} Si ocurre un error durante la ejecución de la transacción.
+ */
+exports.eliminarPedido = async (idPedido) => {
+ const conexion = await db.getConnection();
+
+ try {
+ await conexion.beginTransaction();
+
+ // Eliminar las opciones asociadas al pedido
+ const [resultadoOpciones] = await conexion.query(
+ CONSULTAS_PEDIDOS.ELIMINAR_PEDIDO_OPCION,
+ [idPedido]
+ );
+
+ // Eliminar la relación entre empleados y el pedido
+ const [resultadoEmpleados] = await conexion.query(
+ CONSULTAS_PEDIDOS.ELIMINAR_EMPLEADO_PEDIDO,
+ [idPedido]
+ );
+
+ // Eliminar el pedido
+ const [resultadoPedido] = await conexion.query(
+ CONSULTAS_PEDIDOS.ELIMINAR_PEDIDO,
+ [idPedido]
+ );
+
+ if (resultadoPedido.affectedRows === 0) {
+ throw new Error(`Pedido con ID ${idPedido} no encontrado`);
+ }
+
+ // Confirmar la transacción
+ await conexion.commit();
+
+ return {
+ mensaje: 'Pedido eliminado correctamente',
+ resultadoOpciones,
+ resultadoEmpleados,
+ resultadoPedido,
+ };
+ } catch {
+ await conexion.rollback();
+ throw new Error('Error eliminando pedido');
+ } finally {
+ conexion.release();
+ }
+};
\ No newline at end of file
diff --git a/Pedidos/Datos/Repositorios/repositorioObtenerPedidos.js b/Pedidos/Datos/Repositorios/repositorioObtenerPedidos.js
new file mode 100644
index 00000000..d36d5554
--- /dev/null
+++ b/Pedidos/Datos/Repositorios/repositorioObtenerPedidos.js
@@ -0,0 +1,25 @@
+const CONSULTAS = require('@altertex/util/const/consultasPedidos');
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const MENSAJES = require('@altertex/util/const/mensajesPedidos');
+
+/**
+ * RF60 - Consulta Lista de Pedidos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF60
+ * Consulta la lista de pedidos asociados a un cliente.
+ *
+ * @async
+ * @function obteneLista
+ * @param {number} idCliente - El ID del cliente para el cual se desean obtener los pedidos.
+ * @returns {Promise} Una promesa que se resuelve con un arreglo de objetos que representan los pedidos.
+ * @throws {Error} Lanza un error si el ID del cliente es inválido o si ocurre un error al ejecutar la consulta.
+ */
+exports.obteneLista = async (idCliente) => {
+ try {
+ if (!idCliente || typeof idCliente !== 'number') {
+ throw new Error(MENSAJES.ERROR_CONSULTAR_PEDIDOS.mensaje);
+ }
+
+ return correrQuery(CONSULTAS.OBTENER_LISTA, [idCliente]);
+ } catch {
+ throw new Error(MENSAJES.ERROR_CONSULTAR_PEDIDOS.mensaje);
+ }
+};
diff --git a/Pedidos/Rutas/RutasIndividuales/actualizarPedidos.routes.js b/Pedidos/Rutas/RutasIndividuales/actualizarPedidos.routes.js
new file mode 100644
index 00000000..90ba4c2a
--- /dev/null
+++ b/Pedidos/Rutas/RutasIndividuales/actualizarPedidos.routes.js
@@ -0,0 +1,24 @@
+const express = require('express');
+const ruteador = express.Router();
+
+const controlador = require('@altertex/pedidos/ctrl/actualizarPedido.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticiones = require('@altertex/util/inter/limitePeticiones');
+const RUTAS = require('@altertex/util/const/rutas');
+const PERMISOS = require('@altertex/util/const/permisos');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+
+// RF[62] - Actualizar Pedido
+ruteador.put(
+ RUTAS.PEDIDOS.ACTUALIZAR_PEDIDO,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticiones,
+ verificarPermisos(PERMISOS.ACTUALIZAR_PEDIDO),
+ validarYSanitizar,
+ controlador.actualizarPedido
+);
+
+module.exports = ruteador;
diff --git a/Pedidos/Rutas/RutasIndividuales/eliminarPedidos.routes.js b/Pedidos/Rutas/RutasIndividuales/eliminarPedidos.routes.js
new file mode 100644
index 00000000..6805499c
--- /dev/null
+++ b/Pedidos/Rutas/RutasIndividuales/eliminarPedidos.routes.js
@@ -0,0 +1,79 @@
+//RF[63] Elimina pedido - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF63]
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/pedidos/ctrl/eliminarPedidos.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/pedidos/eliminar:
+ * post:
+ * summary: Eliminar pedidos.
+ * description: Elimina uno o varios pedidos de la base de datos. Requiere autenticación y permisos específicos.
+ * tags:
+ * - Pedidos
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * idsPedido:
+ * type: array
+ * items:
+ * type: integer
+ * example: [101, 102, 103]
+ * responses:
+ * 200:
+ * description: Pedidos eliminados exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Pedidos eliminados correctamente.
+ * 404:
+ * description: Pedidos no encontrados.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No se encontraron los pedidos especificados.
+ * 500:
+ * description: Error interno al eliminar los pedidos.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error al eliminar los pedidos.
+ */
+
+ruteador.post(
+ RUTAS.PEDIDOS.ELIMINAR_PEDIDO,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.ELIMINAR_PEDIDO),
+ controlador.eliminarPedido
+);
+
+module.exports = ruteador;
diff --git a/Pedidos/Rutas/RutasIndividuales/obtenerPedidos.routes.js b/Pedidos/Rutas/RutasIndividuales/obtenerPedidos.routes.js
new file mode 100644
index 00000000..4d0a42b8
--- /dev/null
+++ b/Pedidos/Rutas/RutasIndividuales/obtenerPedidos.routes.js
@@ -0,0 +1,78 @@
+const express = require('express');
+const ruteador = express.Router();
+const RUTAS = require('@altertex/util/const/rutas');
+const PERMISOS = require('@altertex/util/const/permisos');
+const controlador = require('@altertex/pedidos/ctrl/obtenerPedidos.controller');
+
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+/**
+ * RF60 - Consulta Lista de Pedidos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF60
+ * @swagger
+ * /api/pedidos/consultar-lista:
+ * get:
+ * summary: Consulta la lista de pedidos del cliente autenticado
+ * tags:
+ * - Pedidos
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * responses:
+ * 200:
+ * description: Lista de pedidos obtenida exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Lista de pedidos obtenida exitosamente.
+ * pedidos:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * idPedido:
+ * type: integer
+ * example: 1
+ * nombreEmpleado:
+ * type: string
+ * example: Sofía Navarro
+ * fechaOrden:
+ * type: string
+ * format: date
+ * example: 2025-03-20
+ * estatusPedido:
+ * type: string
+ * example: En Proceso
+ * precioTotal:
+ * type: string
+ * example: "450.00"
+ * estatusPago:
+ * type: string
+ * example: Pendiente
+ * estatusEnvio:
+ * type: string
+ * example: En Proceso
+ * 204:
+ * description: No se encontraron pedidos para el cliente.
+ * 403:
+ * description: No tiene permiso para consultar pedidos.
+ * 500:
+ * description: Error al consultar la lista de pedidos.
+ */
+ruteador.get(
+ RUTAS.PEDIDOS.CONSULTAR_LISTA,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CONSULTAR_PEDIDOS),
+ controlador.obtenerLista
+);
+
+module.exports = ruteador;
diff --git a/Pedidos/Rutas/indexPedidos.routes.js b/Pedidos/Rutas/indexPedidos.routes.js
new file mode 100644
index 00000000..16647e25
--- /dev/null
+++ b/Pedidos/Rutas/indexPedidos.routes.js
@@ -0,0 +1,12 @@
+const express = require('express');
+const ruteador = express.Router();
+const rutasObtenerPedidos = require('@altertex/pedidos/rutasInd/obtenerPedidos.routes');
+const rutasEliminarPedido = require('@altertex/pedidos/rutasInd/eliminarPedidos.routes');
+const rutasActualizarPedidos = require('@altertex/pedidos/rutasInd/actualizarPedidos.routes');
+const RUTAS = require('@altertex/util/const/rutas');
+
+ruteador.use(RUTAS.PEDIDOS.BASE, rutasObtenerPedidos);
+ruteador.use(RUTAS.PEDIDOS.BASE, rutasEliminarPedido);
+ruteador.use(RUTAS.PEDIDOS.BASE, rutasActualizarPedidos);
+
+module.exports = ruteador;
diff --git a/Productos/Controladores/consultarProductos.controller.js b/Productos/Controladores/consultarProductos.controller.js
new file mode 100644
index 00000000..7a3feb18
--- /dev/null
+++ b/Productos/Controladores/consultarProductos.controller.js
@@ -0,0 +1,53 @@
+// RF[27] Consulta Lista de Productos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF27]
+
+const repositorio = require('@altertex/pro/repos/repositorioConsultarProductos');
+const obtenerImagenFolder = require('@altertex/util/ser/obtenerImagenFolder');
+const MENSAJES_PRODUCTOS = require('@altertex/util/const/mensajesProductos');
+
+/**
+ * Consulta los productos disponibles para un cliente seleccionado y asigna imágenes por defecto si no se encuentran imágenes.
+ *
+ * Obtiene la lista de productos mediante el repositorio `obtenerProductos`. Si no se encuentran productos o si hay un
+ * error al obtener las imágenes, se asignan imágenes por defecto a los productos. Finalmente, se devuelve la lista de
+ * productos con las imágenes asignadas.
+ *
+ * @param {Express.Request} req - La solicitud HTTP que contiene el ID del cliente en el usuario autenticado (`req.user.clienteSeleccionado`).
+ * @param {Express.Response} res - La respuesta HTTP para enviar el resultado al cliente.
+ * @returns {Promise} Responde con la lista de productos actualizada o un mensaje de error.
+ */
+exports.consultarProductos = async (req, res) => {
+ const idCliente = parseInt(req.user.clienteSeleccionado);
+
+ try {
+ const productos = await repositorio.obtenerProductos(idCliente);
+ req.productos = productos;
+
+ if (!productos || productos.length === 0) {
+ return res.status(200).json({
+ mensaje: MENSAJES_PRODUCTOS.SIN_RESULTADOS.mensaje,
+ });
+ }
+
+ const folder = 'productos/';
+
+ let productosActualizados;
+ try {
+ productosActualizados = await obtenerImagenFolder(req, folder);
+ } catch {
+ productosActualizados = productos.map((producto) => ({
+ ...producto,
+ urlImagen: '/placeholder.png',
+ }));
+ }
+
+ return res.status(MENSAJES_PRODUCTOS.CONSULTA_EXITOSA.codigo).json({
+ mensaje: MENSAJES_PRODUCTOS.CONSULTA_EXITOSA.mensaje,
+ listaProductos: productosActualizados,
+ });
+ } catch (error) {
+ return res.status(MENSAJES_PRODUCTOS.ERROR_CONSULTAR_PRODUCTOS.codigo).json({
+ mensaje: MENSAJES_PRODUCTOS.ERROR_CONSULTAR_PRODUCTOS.mensaje,
+ error: error.message,
+ });
+ }
+};
diff --git a/Productos/Controladores/crearProducto.controller.js b/Productos/Controladores/crearProducto.controller.js
new file mode 100644
index 00000000..8852ef24
--- /dev/null
+++ b/Productos/Controladores/crearProducto.controller.js
@@ -0,0 +1,179 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+const multer = require('multer');
+const enviarS3 = require('@altertex/util/ser/enviarS3');
+const MENSAJES_PRODUCTOS = require('@altertex/util/const/mensajesProductos');
+const validarProducto = require('@altertex/util/vali/validarProducto');
+const validarVariante = require('@altertex/util/vali/validarVariante');
+const validarOpciones = require('@altertex/util/vali/validarOpciones');
+const repositorioCrearProducto = require('@altertex/pro/repos/repositorioCrearProducto');
+const repositorioProductoImagen = require('@altertex/pro/repos/repositorioProductoImagen');
+const repositorioCrearVariante = require('@altertex/pro/repos/repositorioCrearVariante');
+const repositorioVarianteImagen = require('@altertex/pro/repos/repositorioVarianteImagen');
+const repositorioCrearOpcion = require('@altertex/pro/repos/repositorioCrearOpcion');
+// Updated to use the connection pool correctly
+const db = require('@altertex/util/bd/db');
+
+const upload = multer({ storage: multer.memoryStorage() });
+
+// Controller code remains the same but with updated transaction handling
+exports.crearProducto = [
+ upload.fields([
+ { name: 'imagenProducto', maxCount: 1 },
+ { name: 'imagenesVariante', maxCount: 100 },
+ ]),
+
+ async (req, res) => {
+ const idCliente = parseInt(req.user.clienteSeleccionado);
+ const producto = JSON.parse(req.body.producto);
+ const variantes = JSON.parse(req.body.variantes);
+ const mapaImagenes = JSON.parse(req.body.mapaImagenes);
+ const imagenProducto = req.files.imagenProducto ? req.files.imagenProducto[0] : null;
+ const imagenesVariante = req.files.imagenesVariante || [];
+ let conexion = null;
+
+ // prettier-ignore
+ if (
+ !idCliente
+ || !mapaImagenes
+ || !producto
+ || !Array.isArray(variantes)
+ || variantes.length === 0
+ || !imagenProducto
+ || !imagenesVariante
+ ) {
+ return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({
+ mensaje: MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.mensaje,
+ });
+ }
+
+ const errorProducto = validarProducto(producto);
+ if (errorProducto) {
+ return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({
+ mensaje: errorProducto.error,
+ });
+ }
+
+ if (imagenesVariante.length !== mapaImagenes.length) {
+ return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({
+ mensaje: 'La cantidad de imágenes no coincide con el mapa de imágenes',
+ });
+ }
+
+ try {
+ // Get connection from the pool
+ conexion = await db.getConnection();
+ await conexion.beginTransaction();
+
+ const idProducto = await repositorioCrearProducto.crearProducto(idCliente, producto);
+ if (!idProducto) {
+ throw new Error('Error al crear producto');
+ }
+
+ const varianteIdMap = {};
+ const variantesPromises = variantes.map(async (variante) => {
+ const errorVariante = validarVariante({
+ nombreVariante: variante.nombreVariante,
+ descripcion: variante.descripcion,
+ });
+ if (errorVariante) {
+ throw new Error(errorVariante.error);
+ }
+
+ // Update repositorioCrearVariante if not already updated
+ const idVariante = await repositorioCrearVariante.crearVariante(idProducto, variante);
+ if (!idVariante) {
+ throw new Error('Error al crear variante');
+ }
+
+ varianteIdMap[variante.identificador] = {
+ id: idVariante,
+ nombre: variante.nombreVariante,
+ };
+
+ const errorOpciones = validarOpciones(variante.opciones);
+ if (errorOpciones) {
+ throw new Error(errorOpciones.error);
+ }
+
+ await repositorioCrearOpcion.crearOpcion(idVariante, variante.opciones);
+ });
+
+ await Promise.all(variantesPromises);
+
+ // Upload image processing remains unchanged
+ const urlImagenProductoPromise = imagenProducto
+ ? enviarS3({
+ Bucket: process.env.AWS_BUCKET_NAME,
+ Key: `productos/${imagenProducto.originalname}`,
+ Body: imagenProducto.buffer,
+ ContentType: imagenProducto.mimetype,
+ })
+ : Promise.resolve(null);
+
+ // prettier-ignore
+ const urlImagenVariantePromises = imagenesVariante.map((imagenVariante) =>
+ enviarS3({
+ Bucket: process.env.AWS_BUCKET_NAME,
+ Key: `productos/${imagenVariante.originalname}`,
+ Body: imagenVariante.buffer,
+ ContentType: imagenVariante.mimetype,
+ }));
+
+ const [urlImagenProducto, ...urlImagenVariantes] = await Promise.all([
+ urlImagenProductoPromise,
+ ...urlImagenVariantePromises,
+ ]);
+
+ if ((imagenProducto && !urlImagenProducto) || urlImagenVariantes.includes(null)) {
+ throw new Error('Error al subir imágenes al servidor');
+ }
+
+ if (imagenProducto) {
+ await repositorioProductoImagen.crearImagen(
+ idProducto,
+ imagenProducto.originalname,
+ producto.nombreComun
+ );
+ }
+
+ const imagenesVariantePromises = imagenesVariante.map(async (imagen, index) => {
+ const { idVariante: tempIdVariante } = mapaImagenes[index];
+ const varianteInfo = varianteIdMap[tempIdVariante];
+
+ if (!varianteInfo) {
+ throw new Error(`Variante con ID temporal ${tempIdVariante} no encontrada`);
+ }
+
+ await repositorioVarianteImagen.crearImagen(
+ varianteInfo.id,
+ imagen.originalname,
+ varianteInfo.nombre
+ );
+ });
+
+ await Promise.all(imagenesVariantePromises);
+
+ await conexion.commit();
+ return res.status(200).json({ mensaje: 'Producto creado correctamente' });
+ } catch (error) {
+ if (conexion) await conexion.rollback();
+
+ let errorMensaje = MENSAJES_PRODUCTOS.ERROR_CREAR_PRODUCTO;
+
+ if (error.message.includes('Error al subir imágenes al servidor')) {
+ errorMensaje = MENSAJES_PRODUCTOS.ERROR_ENVIAR_IMAGENES_S3;
+ } else if (error.message.includes('Error al crear variante')) {
+ errorMensaje = MENSAJES_PRODUCTOS.ERROR_CREAR_VARIANTE;
+ } else if (error.message.includes('Error al asociar imagen con variante')) {
+ errorMensaje = MENSAJES_PRODUCTOS.ERROR_CREAR_IMAGEN_VARIANTE;
+ }
+
+ return res.status(errorMensaje.codigo).json({
+ mensaje: errorMensaje.mensaje,
+ error: error.message,
+ });
+ } finally {
+ if (conexion) conexion.release();
+ }
+ },
+];
\ No newline at end of file
diff --git a/Productos/Controladores/eliminarProducto.controller.js b/Productos/Controladores/eliminarProducto.controller.js
new file mode 100644
index 00000000..8e33cca8
--- /dev/null
+++ b/Productos/Controladores/eliminarProducto.controller.js
@@ -0,0 +1,58 @@
+// Importación de la función que elimina productos en el repositorio de datos.
+const { eliminarProductos } = require('@altertex/pro/repos/productosRepositorio');
+
+// Importación de las constantes de mensajes utilizados para respuestas del módulo de productos.
+const {
+ RESPUESTA_ELIMINAR_PRODUCTO_EXITOSA,
+ RESPUESTA_ERROR_GENERAL,
+} = require('../../Utilidades/Constantes/mensajesProductos');
+
+/**
+ * RF30 - Eliminar Producto
+ * Requerimiento funcional:
+ * https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF30
+ */
+
+/**
+ * Controlador encargado de eliminar uno o múltiples productos.
+ *
+ * @async
+ * @function eliminarProductoController
+ * @param {object} req - Objeto de solicitud HTTP (Request). Debe contener en el body un array de IDs bajo `req.body.ids`.
+ * @param {object} res - Objeto de respuesta HTTP (Response).
+ * @returns {Promise} No retorna datos directamente; envía la respuesta HTTP al cliente.
+ *
+ * @description
+ * Recibe un array de IDs de productos a eliminar a través del cuerpo de la solicitud (body).
+ * Valida que los IDs sean un arreglo no vacío. Llama al repositorio para realizar la eliminación
+ * y responde al cliente con éxito o error según corresponda.
+ */
+const eliminarProductoController = async (req, res) => {
+ try {
+ const { ids } = req.body;
+
+ // Validación de los IDs recibidos.
+ if (!Array.isArray(ids) || ids.length === 0) {
+ return res.status(400).json({
+ codigo: 400,
+ mensaje: 'Debes proporcionar al menos un ID de producto para eliminar.',
+ });
+ }
+ // Se realiza la eliminación de los productos.
+ const resultado = await eliminarProductos(ids);
+
+ // Se responde dependiendo del éxito o fallo de la operación.
+ if (resultado) {
+ return res.status(200).json(RESPUESTA_ELIMINAR_PRODUCTO_EXITOSA);
+ } else {
+ return res.status(400).json(RESPUESTA_ERROR_GENERAL);
+ }
+ } catch {
+ return res.status(500).json(RESPUESTA_ERROR_GENERAL);
+ }
+};
+
+// Exporta el controlador para su uso en las rutas correspondientes.
+module.exports = {
+ eliminarProductoController,
+};
diff --git a/Productos/Controladores/exportarProductos.controller.js b/Productos/Controladores/exportarProductos.controller.js
new file mode 100644
index 00000000..ebdd243c
--- /dev/null
+++ b/Productos/Controladores/exportarProductos.controller.js
@@ -0,0 +1,49 @@
+const repositorio = require('@altertex/pro/repos/repositorioExportarProducto');
+const MENSAJES_PRODUCTOS = require('@altertex/util/const/mensajesProductos');
+
+/**
+ * Controlador para exportar productos seleccionados de un cliente y retornar Excel.
+ *
+ * @async
+ * @function exportarProductos
+ * @param {Request} req
+ * @param {Response} res
+ * @returns {Response} Archivo Excel con los productos exportados
+ * @see [RF58 - Exportar Productos](https://codeandco-wiki.netlify.app/docs/next/proyectos/textiles/documentacion/requisitos/RF58)
+ */
+exports.exportarProductos = async (req, res) => {
+ try {
+ const idCliente = parseInt(req.user.clienteSeleccionado);
+ const idsProducto = req.body.idsProducto;
+
+ if (!Array.isArray(idsProducto) || idsProducto.length === 0) {
+ return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({
+ mensaje: 'Debes seleccionar al menos un producto para exportar.',
+ });
+ }
+
+ const idsSeleccionados = idsProducto.map((id) => parseInt(id));
+ const productos = await repositorio.obtenerProductosExportacion(idCliente, idsSeleccionados);
+
+ if (!productos || productos.length === 0) {
+ return res.status(MENSAJES_PRODUCTOS.PRODUCTOS_NO_ENCONTRADOS.codigo).json({
+ mensaje: MENSAJES_PRODUCTOS.PRODUCTOS_NO_ENCONTRADOS.mensaje,
+ });
+ }
+
+ const buffer = await repositorio.generarArchivoExcel(productos);
+
+ res.setHeader('Content-Disposition', 'attachment; filename=productos.xlsx');
+ res.setHeader(
+ 'Content-Type',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+ );
+
+ return res.send(buffer);
+ } catch (error) {
+ console.error('Error al exportar productos:', error);
+ return res.status(MENSAJES_PRODUCTOS.ERROR_EXPORTACION.codigo).json({
+ mensaje: MENSAJES_PRODUCTOS.ERROR_EXPORTACION.mensaje,
+ });
+ }
+};
diff --git a/Productos/Controladores/importarProductos.controller.js b/Productos/Controladores/importarProductos.controller.js
new file mode 100644
index 00000000..35c59d7a
--- /dev/null
+++ b/Productos/Controladores/importarProductos.controller.js
@@ -0,0 +1,141 @@
+const validarVariante = require('@altertex/util/vali/validarVarianteImportar');
+const validarOpcionesImportar = require('@altertex/util/vali/validarOpcionesImportar');
+const repositorioCrearProducto = require('@altertex/pro/repos/repositorioCrearProducto');
+const repositorioCrearVariante = require('@altertex/pro/repos/repositorioCrearVariante');
+const repositorioCrearOpcion = require('@altertex/pro/repos/repositorioCrearOpcion');
+const db = require('@altertex/util/bd/db');
+const validarProductoImportado = require('@altertex/util/vali/validarProductoImportado');
+const { crearGeneradorSKUConsecutivo } = require('@altertex/util/inter/generarSKUAuto');
+const { proveedorExiste } = require('@altertex/pro/repos/repositorioValidarProveedor');
+
+
+/**
+ * Importa productos y sus variantes/opciones para un cliente.
+ *
+ * Espera en req.body un array de objetos con la forma:
+ * [
+ * {
+ * producto: { ... },
+ * variantes: [
+ * {
+ * ...,
+ * opciones: { ... }
+ * }
+ * ]
+ * }
+ * ]
+ *
+ * Valida cada producto, variante y opciones antes de insertar en la base de datos.
+ * Si hay errores en alguna fila, los acumula y los devuelve al finalizar.
+ *
+ * @async
+ * @function importarProductos
+ * @param {Express.Request} req - Request de Express, requiere req.user.clienteSeleccionado y req.body.
+ * @param { Express.Response} res - Response de Express.
+ * @returns {Promise} Devuelve un JSON con el resultado de la importación y los errores encontrados.
+ *
+ * @see RF[56] Leer producto - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF56]
+ */
+exports.importarProductos = async (req, res) => {
+ const idCliente = parseInt(req.user.clienteSeleccionado);
+ const productos = req.body;
+
+ const MENSAJE_PRODUCTOS_INVALIDOS = 'No se recibieron productos válidos.'
+ const MENSAJE_VARIANTES_INVALIDAS = 'No se recibieron productos válidos.'
+ const MENSAJE_ERRORES_ARCHIVO = 'Se encontraron errores en el archivo.'
+ const IMPORTACION_EXITOSA = 'Importación completada exitosamente.';
+ const ERROR_AL_IMPORTAR = 'Error al importar productos.';
+
+ if (!Array.isArray(productos) || productos.length === 0) {
+ return res.status(400).json({ mensaje: MENSAJE_PRODUCTOS_INVALIDOS});
+ }
+
+ const errores = [];
+ let conexion = null;
+
+ try {
+ conexion = await db.getConnection();
+ await conexion.beginTransaction();
+
+ for (let im = 0; im < productos.length; im += 1) {
+ const { producto, variantes } = productos[im];
+ const fila = im + 1;
+
+ const errorProducto = validarProductoImportado(producto);
+ if (errorProducto) {
+ errores.push({ fila, error: errorProducto.error });
+ continue;
+ }
+ if (producto.idProveedor !== null) {
+ const existe = await proveedorExiste(conexion, producto.idProveedor);
+ if (!existe) {
+ errores.push({ fila, error: `idProveedor ${producto.idProveedor} no existe en la base de datos.` });
+ continue;
+ }
+ }
+
+ if (!Array.isArray(variantes) || variantes.length === 0) {
+ errores.push({ fila, error: MENSAJE_VARIANTES_INVALIDAS });
+ continue;
+ }
+
+ for (const variante of variantes) {
+ const errorVariante = validarVariante(variante);
+ if (errorVariante) {
+ errores.push({ fila, error: errorVariante.error });
+ continue;
+ }
+
+ const errorOpciones = validarOpcionesImportar(variante.opciones);
+ if (errorOpciones) {
+ errores.push({ fila, error: errorOpciones.error });
+ continue;
+ }
+ }
+ }
+
+ if (errores.length > 0) {
+ await conexion.rollback();
+ return res.status(200).json({
+ mensaje: MENSAJE_ERRORES_ARCHIVO,
+ errores,
+ });
+ }
+ const generarSKUConsecutivo = crearGeneradorSKUConsecutivo();
+ for (let indice = 0; indice < productos.length; indice += 1) {
+ const { producto, variantes } = productos[indice];
+ const idProducto = await repositorioCrearProducto.crearProducto(idCliente, producto);
+
+ for (const variante of variantes) {
+ const idVariante = await repositorioCrearVariante.crearVariante(idProducto, variante);
+
+ const opcionesConSKU = variante.opciones.map(opcion => ({
+ ...opcion,
+ SKUautomatico: generarSKUConsecutivo(
+ producto.nombreComun,
+ variante.nombreVariante,
+ opcion.valorOpcion || 'SINVALOR'
+ )
+ }));
+
+ await repositorioCrearOpcion.crearOpcion(idVariante, opcionesConSKU);
+ }
+ }
+
+ await conexion.commit();
+
+ return res.status(200).json({
+ mensaje: IMPORTACION_EXITOSA,
+ errores: null,
+ });
+
+ } catch (err) {
+ if (conexion) await conexion.rollback();
+ return res.status(500).json({
+ mensaje: ERROR_AL_IMPORTAR,
+ error: err.message,
+ });
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
diff --git a/Productos/Controladores/leerProducto.controller.js b/Productos/Controladores/leerProducto.controller.js
new file mode 100644
index 00000000..5303e6f6
--- /dev/null
+++ b/Productos/Controladores/leerProducto.controller.js
@@ -0,0 +1,38 @@
+const MENSAJES = require('@altertex/util/const/mensajesProductos');
+const repositorio = require('@altertex/pro/repos/repositorioLeerProducto');
+// RF[28] Leer producto - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF28]
+
+/**
+ * Controlador para leer la información de un producto específico.
+ *
+ * Este endpoint espera que el `idProducto` se encuentre en el cuerpo de la solicitud
+ * y que el `idCliente` esté disponible en el objeto `req.user.clienteSeleccionado`.
+ *
+ * @async
+ * @function leerProducto
+ * @param {Express.Request} req - Objeto de solicitud de Express.
+ * @param {object} req.body - Cuerpo de la solicitud.
+ * @param {string|number} req.body.idProducto - ID del producto a consultar.
+ * @param {object} req.user - Usuario autenticado con un cliente seleccionado.
+ * @param {string|number} req.user.clienteSeleccionado - ID del cliente asociado.
+ * @param {Express.Response} res - Objeto de respuesta de Express.
+ * @returns {Promise} Retorna una respuesta HTTP con la información del producto o un mensaje de error.
+ * @throws {Error} Lanza un error si `idProducto` no es válido o si ocurre un error al consultar el repositorio.
+ */
+exports.leerProducto = async (req, res) => {
+ const idProducto = req.query.idProducto;
+ const idCliente = req.user.clienteSeleccionado;
+
+ if (!idProducto) {
+ return res.status(MENSAJES.ID_INVALIDO.codigo).json({ mensaje: MENSAJES.ID_INVALIDO.mensaje });
+ }
+
+ try {
+ const infoProducto = await repositorio.leerProducto(idProducto, idCliente);
+ return res.status(MENSAJES.LEER_PRODUCTO_EXITO.codigo).json({
+ infoProducto,
+ });
+ } catch (error) {
+ return res.status(MENSAJES.ERROR_LEER_PRODUCTO.codigo).json({ mensaje: error.message });
+ }
+};
\ No newline at end of file
diff --git a/Productos/Datos/Repositorios/productosRepositorio.js b/Productos/Datos/Repositorios/productosRepositorio.js
new file mode 100644
index 00000000..5af72a09
--- /dev/null
+++ b/Productos/Datos/Repositorios/productosRepositorio.js
@@ -0,0 +1,49 @@
+// RF[30] Eliminar Producto - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF30]
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const consultas = require('@altertex/util/const/consultasProductos');
+const extraerNombreArchivoS3 = require('@altertex/util/ser/extraerNombreArchivoS3');
+const eliminarImagenS3 = require('@altertex/util/ser/eliminarImagenS3');
+
+/**
+ * Funcion para eliminar productos de la base de datos.
+ *
+ * RF30 - Eliminar Producto - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF30]
+ *
+ * @async
+ * @function eliminarProductos
+ * @param {Array} ids - Array de IDs de productos a eliminar.
+ *
+ * @returns {Promise} Resultado de la eliminación.
+ * @throws {Error} Si ocurre un error al ejecutar la consulta.
+ * - Retorna true si se eliminaron productos, false en caso contrario.
+ */
+const eliminarProductos = async (ids) => {
+ try {
+ // 1. Obtener imágenes asociadas
+ const placeholders = ids.map(() => '?').join(',');
+ const queryObtenerImagenes = consultas.OBTENER_IMAGENES_POR_IDS.replace('(?)', `(${placeholders})`);
+ const imagenes = await correrQuery(queryObtenerImagenes, ids);
+
+ // 2. Eliminar imágenes válidas
+ for (const img of imagenes) {
+ if (img.urlImagen && !img.urlImagen.includes('placeholder')) {
+ const nombreReal = extraerNombreArchivoS3(img.urlImagen);
+ if (nombreReal) {
+ await eliminarImagenS3('productos/', nombreReal);
+ }
+ }
+ }
+
+ // 3. Eliminar productos
+ const queryEliminar = consultas.ELIMINAR_PRODUCTOS.replace('(?)', `(${placeholders})`);
+ const resultado = await correrQuery(queryEliminar, ids);
+
+ return resultado?.affectedRows > 0;
+ } catch {
+ return false;
+ }
+};
+
+module.exports = {
+ eliminarProductos,
+};
\ No newline at end of file
diff --git a/Productos/Datos/Repositorios/repositorioConsultarProductos.js b/Productos/Datos/Repositorios/repositorioConsultarProductos.js
new file mode 100644
index 00000000..66d90862
--- /dev/null
+++ b/Productos/Datos/Repositorios/repositorioConsultarProductos.js
@@ -0,0 +1,22 @@
+// RF[27] Consulta Lista de Productos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF27]
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const consultas = require('@altertex/util/const/consultasProductos');
+
+/**
+ * Obtiene la lista de productos disponibles para un cliente seleccionado.
+ *
+ * Realiza una consulta a la base de datos para obtener la lista de productos basándose en el `clienteSeleccionado`.
+ * Si ocurre algún error durante la consulta, se captura y se devuelve un arreglo vacío.
+ *
+ * @param {number} clienteSeleccionado - El ID del cliente para el que se obtendrán los productos.
+ * @returns {Promise} Una lista de productos del cliente o un arreglo vacío si ocurre un error.
+ */
+exports.obtenerProductos = async (clienteSeleccionado) => {
+ const query = consultas.OBTENER_LISTA;
+ try {
+ const resultados = await correrQuery(query, [clienteSeleccionado]);
+ return resultados;
+ } catch {
+ return [];
+ }
+};
diff --git a/Productos/Datos/Repositorios/repositorioCrearOpcion.js b/Productos/Datos/Repositorios/repositorioCrearOpcion.js
new file mode 100644
index 00000000..4237b61d
--- /dev/null
+++ b/Productos/Datos/Repositorios/repositorioCrearOpcion.js
@@ -0,0 +1,43 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+const db = require('@altertex/util/bd/db');
+const consultas = require('@altertex/util/const/consultasOpciones');
+
+/**
+ * Crea una o varias opciones relacionadas con una variante.
+ *
+ * @async
+ * @function crearOpcion
+ * @param {number} idVariante - ID de la variante a la que se le agregarán las opciones.
+ * @param {Array} opciones - Un arreglo con los objetos de opciones que se desean agregar.
+ * @returns {Promise} - Una promesa que se resuelve cuando todas las opciones se crean exitosamente.
+ */
+exports.crearOpcion = async (idVariante, opciones) => {
+ const conexion = await db.getConnection();
+
+ try {
+ await conexion.beginTransaction();
+
+ for (const opcion of opciones) {
+ const params = [
+ idVariante,
+ opcion.cantidad,
+ opcion.valorOpcion,
+ opcion.SKUautomatico,
+ opcion.SKUcomercial,
+ opcion.costoAdicional,
+ opcion.descuento,
+ opcion.estado,
+ ];
+
+ await conexion.query(consultas.CREAR, params);
+ }
+
+ await conexion.commit();
+ } catch (error) {
+ await conexion.rollback();
+ console.error('Error al crear opciones:', error);
+ throw error;
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
\ No newline at end of file
diff --git a/Productos/Datos/Repositorios/repositorioCrearProducto.js b/Productos/Datos/Repositorios/repositorioCrearProducto.js
new file mode 100644
index 00000000..92cb133e
--- /dev/null
+++ b/Productos/Datos/Repositorios/repositorioCrearProducto.js
@@ -0,0 +1,63 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+const db = require('@altertex/util/bd/db');
+const consultas = require('@altertex/util/const/consultasProductos');
+
+/**
+ * Crea un nuevo producto en la base de datos.
+ *
+ * Esta función ejecuta una consulta SQL para insertar un producto en la base de datos,
+ * utilizando los parámetros proporcionados. Devuelve el ID del producto recién creado
+ * en caso de éxito, o un array vacío si ocurre algún error durante la operación.
+ *
+ * @param {number} clienteSeleccionado - ID del cliente para el cual se está creando el producto.
+ * @param {object} producto - Objeto que contiene la información del producto.
+ * @param {number} producto.idProveedor - ID del proveedor asociado al producto.
+ * @param {string} producto.nombreComun - Nombre común del producto.
+ * @param {string} producto.nombreComercial - Nombre comercial del producto.
+ * @param {string} producto.descripcion - Descripción del producto.
+ * @param {string} producto.marca - Marca del producto.
+ * @param {string} producto.modelo - Modelo del producto.
+ * @param {string} producto.tipoProducto - Tipo del producto.
+ * @param {number} producto.precioPuntos - Precio en puntos del producto.
+ * @param {number} producto.precioCliente - Precio para el cliente del producto.
+ * @param {number} producto.precioVenta - Precio de venta del producto.
+ * @param {number} producto.costo - Costo de producción del producto.
+ * @param {number} producto.impuesto - Impuesto aplicado al producto.
+ * @param {number} producto.descuento - Descuento aplicado al producto.
+ * @param {string} producto.estado - Estado del producto (activo/inactivo).
+ * @param {boolean} producto.envio - Indica si el producto es apto para envío.
+ *
+ * @returns {number|Array} El ID del producto recién creado en caso de éxito, o un array vacío en caso de error.
+ */
+exports.crearProducto = async (clienteSeleccionado, producto) => {
+ const conexion = await db.getConnection();
+
+ try {
+ const [resultados] = await conexion.query(consultas.CREAR, [
+ clienteSeleccionado,
+ producto.idProveedor,
+ producto.nombreComun,
+ producto.nombreComercial,
+ producto.descripcion,
+ producto.marca,
+ producto.modelo,
+ producto.tipoProducto,
+ producto.precioPuntos,
+ producto.precioCliente,
+ producto.precioVenta,
+ producto.costo,
+ producto.impuesto,
+ producto.descuento,
+ producto.estado,
+ producto.envio,
+ ]);
+
+ const idProducto = resultados.insertId;
+ return idProducto;
+ } catch (error) {
+ console.error('Error al crear producto:', error);
+ return [];
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
\ No newline at end of file
diff --git a/Productos/Datos/Repositorios/repositorioCrearVariante.js b/Productos/Datos/Repositorios/repositorioCrearVariante.js
new file mode 100644
index 00000000..5579abdc
--- /dev/null
+++ b/Productos/Datos/Repositorios/repositorioCrearVariante.js
@@ -0,0 +1,37 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+const db = require('@altertex/util/bd/db');
+const consultas = require('@altertex/util/const/consultasVariantes');
+
+/**
+ * Crea una nueva variante para un producto en la base de datos.
+ *
+ * Esta función ejecuta una consulta SQL para insertar una variante asociada a un producto,
+ * utilizando los parámetros proporcionados. Devuelve el ID de la variante recién creada
+ * en caso de éxito, o un array vacío si ocurre algún error durante la operación.
+ *
+ * @param {number} idProducto - ID del producto al que se le va a agregar la variante.
+ * @param {object} variante - Objeto que contiene la información de la variante.
+ * @param {string} variante.nombreVariante - Nombre de la variante (por ejemplo, color, tamaño).
+ * @param {string} variante.descripcion - Descripción de la variante.
+ *
+ * @returns {number|Array} El ID de la variante recién creada en caso de éxito, o un array vacío en caso de error.
+ */
+exports.crearVariante = async (idProducto, variante) => {
+ const conexion = await db.getConnection();
+
+ try {
+ const [resultados] = await conexion.query(consultas.CREAR, [
+ idProducto,
+ variante.nombreVariante,
+ variante.descripcion
+ ]);
+
+ const idVariante = resultados.insertId;
+ return idVariante;
+ } catch (error) {
+ console.error('Error al crear variante:', error);
+ return [];
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
\ No newline at end of file
diff --git a/Productos/Datos/Repositorios/repositorioExportarProducto.js b/Productos/Datos/Repositorios/repositorioExportarProducto.js
new file mode 100644
index 00000000..69b7af2c
--- /dev/null
+++ b/Productos/Datos/Repositorios/repositorioExportarProducto.js
@@ -0,0 +1,135 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_PRODUCTOS = require('@altertex/util/const/consultasProductos');
+const excelJS = require('exceljs');
+
+/**
+ * Consulta la lista de productos seleccionados de un cliente para exportar en CSV.
+ *
+ * @param {number} idCliente
+ * @param {number[]} idsProducto
+ * @returns {Promise>}
+ *
+ * @see [RF58 - Documentación de requisitos](https://codeandco-wiki.netlify.app/docs/next/proyectos/textiles/documentacion/requisitos/RF58)
+ */
+exports.obtenerProductosExportacion = (idCliente, idsProducto) => {
+ const placeholders = idsProducto.map(() => '?').join(', ');
+ const query = CONSULTAS_PRODUCTOS.OBTENER_DATOS_EXPORTACION.replace('__IDS__', placeholders);
+ return correrQuery(query, [idCliente, ...idsProducto]);
+};
+
+/**
+ * Procesa y genera el archivo Excel con los productos exportados
+ * @param {Array} productos Lista de productos a exportar
+ * @returns {Promise} Buffer con el archivo Excel
+ */
+exports.generarArchivoExcel = async (productos) => {
+ const workbook = new excelJS.Workbook();
+
+ // Primera hoja - Información básica del producto
+ const hoja1 = workbook.addWorksheet('Información Producto');
+ hoja1.columns = [
+ { header: 'ID Producto', key: 'idProducto' },
+ { header: 'ID Proveedor', key: 'idProveedor' },
+ { header: 'Nombre Producto', key: 'nombreProducto' },
+ { header: 'Nombre Comercial', key: 'nombreComercial' },
+ { header: 'Descripción', key: 'descripcionProducto' },
+ { header: 'Tipo Producto', key: 'tipoProducto' },
+ { header: 'Marca', key: 'marca' },
+ { header: 'Modelo', key: 'modelo' },
+ { header: 'Costo', key: 'costo' },
+ { header: 'Precio Venta', key: 'precioVenta' },
+ { header: 'Precio Cliente', key: 'precioCliente' },
+ { header: 'Precio Puntos', key: 'precioPuntos' },
+ { header: 'Impuesto', key: 'impuesto' },
+ { header: 'Descuento', key: 'descuento' },
+ { header: 'Estado', key: 'estado' },
+ { header: 'Envío', key: 'envio' },
+ ];
+ hoja1.addRows(productos);
+
+ // Segunda hoja - Información desglosada de variantes
+ const hoja2 = workbook.addWorksheet('Variantes');
+ hoja2.columns = [
+ { header: 'ID Producto', key: 'idProducto' },
+ { header: 'Nombre Producto', key: 'nombreProducto' },
+ { header: 'Nombre Variante', key: 'nombreVariante' },
+ { header: 'Descripción Variante', key: 'descripcionVariante' },
+ ];
+
+ const variantesDesglosadas = procesarVariantes(productos);
+ hoja2.addRows(variantesDesglosadas);
+
+ // Tercera hoja - Información desglosada de opciones
+ const hoja3 = workbook.addWorksheet('Opciones');
+ hoja3.columns = [
+ { header: 'ID Producto', key: 'idProducto' },
+ { header: 'Nombre Producto', key: 'nombreProducto' },
+ { header: 'Nombre Variante', key: 'nombreVariante' },
+ { header: 'Valor Opción', key: 'valorOpcion' },
+ { header: 'SKU Comercial', key: 'skuComercial' },
+ { header: 'SKU Automático', key: 'skuAutomatico' },
+ { header: 'Cantidad', key: 'cantidad' },
+ ];
+
+ const opcionesDesglosadas = procesarOpciones(productos);
+ hoja3.addRows(opcionesDesglosadas);
+
+ return await workbook.xlsx.writeBuffer();
+};
+
+/**
+ * Procesa las variantes de los productos
+ * @param {Array} productos Lista de productos
+ * @returns {Array} Lista de variantes procesadas
+ */
+function procesarVariantes(productos) {
+ return productos.flatMap((producto) => {
+ const variantes = producto.variantes_opciones.split(' | ').map((variante) => {
+ const [datosVariante] = variante.split(',');
+ const [nombreVariante, descripcionVariante] = datosVariante.split('-');
+ return {
+ idProducto: producto.idProducto,
+ nombreProducto: producto.nombreProducto,
+ nombreVariante,
+ descripcionVariante,
+ };
+ });
+ return variantes;
+ });
+}
+
+/**
+ * Procesa las opciones de los productos
+ * @param {Array} productos Lista de productos
+ * @returns {Array} Lista de opciones procesadas
+ */
+function procesarOpciones(productos) {
+ return productos.flatMap((producto) => {
+ return producto.variantes_opciones.split(' | ').flatMap((variante) => {
+ const [datosVariante, ...opcionesParts] = variante.split(',');
+ const [nombreVariante] = datosVariante.split('-');
+ const opcionesCompletas = opcionesParts.join(',').trim();
+
+ if (!opcionesCompletas) return [];
+
+ return opcionesCompletas
+ .split(', ')
+ .filter((opcion) => opcion.trim())
+ .map((opcion) => {
+ const [valorOpcion, skuComercial, skuAutomatico, cantidad] = opcion
+ .split(':')
+ .map((valores) => valores.trim());
+
+ return {
+ idProducto: producto.idProducto,
+ nombreProducto: producto.nombreProducto,
+ nombreVariante,
+ valorOpcion,
+ skuComercial,
+ skuAutomatico,
+ cantidad,
+ };
+ });
+ });
+ });
+}
diff --git a/Productos/Datos/Repositorios/repositorioLeerProducto.js b/Productos/Datos/Repositorios/repositorioLeerProducto.js
new file mode 100644
index 00000000..7c306d02
--- /dev/null
+++ b/Productos/Datos/Repositorios/repositorioLeerProducto.js
@@ -0,0 +1,27 @@
+const CONSULTAS = require('@altertex/util/const/consultasProductos');
+const MENSAJES = require('@altertex/util/const/mensajesProductos');
+const correrQuery = require('@altertex/util/ser/correrQuery');
+
+/**
+ * Lee la información de un producto específico para un cliente dado.
+ *
+ * @async
+ * @function leerProducto
+ * @param {number|string} idProducto - El identificador del producto a consultar.
+ * @param {number|string} idCliente - El identificador del cliente que realiza la consulta.
+ * @returns {Promise} Retorna una promesa que resuelve con los datos del producto si se encuentra.
+ * @throws {Error} Lanza un error si el producto no se encuentra o si ocurre un error durante la consulta.
+ */
+exports.leerProducto = async (idProducto, idCliente) => {
+ try {
+ const resultado = await correrQuery(CONSULTAS.LEER_PRODUCTO, [idProducto, idCliente]);
+
+ if (resultado.length === 0) {
+ throw new Error(MENSAJES.PRODUCTO_NO_ENCONTRADO.mensaje);
+ }
+
+ return resultado;
+ } catch (error) {
+ throw new Error(error.message);
+ }
+};
diff --git a/Productos/Datos/Repositorios/repositorioProductoImagen.js b/Productos/Datos/Repositorios/repositorioProductoImagen.js
new file mode 100644
index 00000000..706b00de
--- /dev/null
+++ b/Productos/Datos/Repositorios/repositorioProductoImagen.js
@@ -0,0 +1,48 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+const db = require('@altertex/util/bd/db');
+const consultasProductos = require('@altertex/util/const/consultasProductos');
+const consultasImagenes = require('@altertex/util/const/consultasImagenes');
+
+/**
+ * Crea una imagen en la base de datos y la asocia a un producto.
+ *
+ * Esta función realiza dos operaciones en una transacción:
+ * - Inserta una nueva imagen en la tabla de imágenes.
+ * - Crea una relación entre la imagen y el producto correspondiente.
+ *
+ * @param {number} idProducto - ID del producto al que se asociará la imagen.
+ * @param {string} urlImagenProducto - URL o ruta de la imagen del producto almacenada.
+ * @param {string} nombreComun - Nombre común o descriptivo asociado al producto.
+ *
+ * @returns {Promise} El resultado de la inserción de la imagen (incluyendo `insertId`) si es exitoso, o un arreglo vacío en caso de error.
+ */
+exports.crearImagen = async (idProducto, urlImagenProducto, nombreComun) => {
+ const parametrosImagen = [urlImagenProducto, 'Imagen Producto', nombreComun];
+ const conexion = await db.getConnection();
+
+ try {
+ await conexion.beginTransaction();
+
+ const [resultadoImagen] = await conexion.query(
+ consultasImagenes.CREAR,
+ parametrosImagen
+ );
+
+ const idImagen = resultadoImagen.insertId;
+
+ const parametrosRelacion = [idImagen, idProducto];
+ await conexion.query(
+ consultasProductos.CREAR_IMAGEN_PRODUCTO,
+ parametrosRelacion
+ );
+
+ await conexion.commit();
+ return resultadoImagen;
+ } catch (error) {
+ console.error('Error al crear o asociar la imagen:', error);
+ await conexion.rollback();
+ return [];
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
\ No newline at end of file
diff --git a/Productos/Datos/Repositorios/repositorioValidarProveedor.js b/Productos/Datos/Repositorios/repositorioValidarProveedor.js
new file mode 100644
index 00000000..7886411c
--- /dev/null
+++ b/Productos/Datos/Repositorios/repositorioValidarProveedor.js
@@ -0,0 +1,19 @@
+const consultas = require('@altertex/util/const/consultasProveedores');
+
+
+/**
+ * Verifica si un proveedor existe en la base de datos.
+ * @param {object} conexion - La conexión a la base de datos.
+ * @param {number|null} idProveedor - El ID del proveedor a verificar.
+ * @returns {Promise} True si el proveedor existe o si idProveedor es null.
+ */
+async function proveedorExiste(conexion, idProveedor) {
+ if (idProveedor === null) return true; // Permitido por diseño
+ const [result] = await conexion.query(
+ consultas.VERIFICAR_EXISTE,
+ [idProveedor]
+ );
+ return result.length > 0;
+}
+
+module.exports = { proveedorExiste };
diff --git a/Productos/Datos/Repositorios/repositorioVarianteImagen.js b/Productos/Datos/Repositorios/repositorioVarianteImagen.js
new file mode 100644
index 00000000..46686dcb
--- /dev/null
+++ b/Productos/Datos/Repositorios/repositorioVarianteImagen.js
@@ -0,0 +1,48 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+const db = require('@altertex/util/bd/db');
+const consultasVariantes = require('@altertex/util/const/consultasVariantes');
+const consultasImagenes = require('@altertex/util/const/consultasImagenes');
+
+/**
+ * Crea una imagen en la base de datos y la asocia a una variante de producto.
+ *
+ * Esta función realiza dos operaciones dentro de una transacción:
+ * - Inserta una nueva imagen en la tabla de imágenes.
+ * - Crea una relación entre la imagen y la variante correspondiente.
+ *
+ * @param {number} idVariante - ID de la variante a la que se asociará la imagen.
+ * @param {string} urlImagenVariante - URL o ruta de la imagen de la variante almacenada.
+ * @param {string} nombreComun - Nombre común o descriptivo asociado a la variante.
+ *
+ * @returns {Promise} El resultado de la inserción de la imagen (incluyendo `insertId`) si es exitoso, o un arreglo vacío en caso de error.
+ */
+exports.crearImagen = async (idVariante, urlImagenVariante, nombreComun) => {
+ const parametrosImagen = [urlImagenVariante, 'Imagen Variante', nombreComun];
+ const conexion = await db.getConnection();
+
+ try {
+ await conexion.beginTransaction();
+
+ const [resultadoImagen] = await conexion.query(
+ consultasImagenes.CREAR,
+ parametrosImagen
+ );
+
+ const idImagen = resultadoImagen.insertId;
+
+ const parametrosRelacion = [idImagen, idVariante];
+ await conexion.query(
+ consultasVariantes.CREAR_IMAGEN_VARIANTE,
+ parametrosRelacion
+ );
+
+ await conexion.commit();
+ return resultadoImagen;
+ } catch (error) {
+ console.error('Error al crear o asociar la imagen:', error);
+ await conexion.rollback();
+ return [];
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
\ No newline at end of file
diff --git a/Productos/Rutas/RutasIndividuales/consultarProductos.routes.js b/Productos/Rutas/RutasIndividuales/consultarProductos.routes.js
new file mode 100644
index 00000000..16475b06
--- /dev/null
+++ b/Productos/Rutas/RutasIndividuales/consultarProductos.routes.js
@@ -0,0 +1,74 @@
+//RF27 Consulta Lista de Productos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF27
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/pro/ctrl/consultarProductos.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/productos/consultar-lista:
+ * post:
+ * summary: Consultar productos
+ * tags: [Productos]
+ * security:
+ * - ApiKeyAuth: []
+ * requestBody:
+ * required: false
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * filtros:
+ * type: object
+ * description: Opcional, filtros para la búsqueda
+ * responses:
+ * 200:
+ * description: Consulta de productos exitosa
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Lista de productos consultada correctamente
+ * productos:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * idProducto:
+ * type: integer
+ * example: 1
+ * nombreComun:
+ * type: string
+ * example: Camiseta básica
+ * claveProducto:
+ * type: string
+ * example: CAM-001
+ * activo:
+ * type: boolean
+ * example: true
+ * 401:
+ * description: No autorizado - Credenciales inválidas o sin permisos
+ * 500:
+ * description: Error del servidor al obtener los productos
+ */
+
+ruteador.post(
+ RUTAS.PRODUCTOS.CONSULTAR_LISTA,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CONSULTAR_PRODUCTOS),
+ controlador.consultarProductos
+);
+
+module.exports = ruteador;
diff --git a/Productos/Rutas/RutasIndividuales/crearProducto.routes.js b/Productos/Rutas/RutasIndividuales/crearProducto.routes.js
new file mode 100644
index 00000000..f8d4f63c
--- /dev/null
+++ b/Productos/Rutas/RutasIndividuales/crearProducto.routes.js
@@ -0,0 +1,118 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/pro/ctrl/crearProducto.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/productos/crear:
+ * post:
+ * summary: Crear un nuevo producto
+ * tags: [Productos]
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * consumes:
+ * - multipart/form-data
+ * requestBody:
+ * required: true
+ * content:
+ * multipart/form-data:
+ * schema:
+ * type: object
+ * required:
+ * - producto
+ * - variantes
+ * - mapaImagenes
+ * - imagenProducto
+ * - imagenesVariante
+ * properties:
+ * producto:
+ * type: string
+ * format: json
+ * description: Información del producto en formato JSON
+ * example: '{"nombreComun":"Camisa casual","nombreComercial":"Camisa formal","descripcion":"Camisa de algodón","marca":"Brand","modelo":"M-123","tipoProducto":"Ropa","precioPuntos":100,"precioCliente":50.99,"precioVenta":59.99,"costo":30.00,"impuesto":16,"descuento":0,"idProveedor":1,"estado":1,"envio":1}'
+ * variantes:
+ * type: string
+ * format: json
+ * description: Array de variantes del producto en formato JSON
+ * example: '[{"identificador":"var1","nombreVariante":"Color","descripcion":"Color de la prenda","opciones":[{"valorOpcion":"Azul","cantidad":10,"descuento":0,"costoAdicional":0,"SKUautomatico":"SKU-AUTO-1","SKUcomercial":"SKU-COM-1"}]}]'
+ * mapaImagenes:
+ * type: string
+ * format: json
+ * description: Mapa que relaciona imágenes con variantes en formato JSON
+ * example: '[{"idVariante":"var1"}]'
+ * imagenProducto:
+ * type: string
+ * format: binary
+ * description: Imagen principal del producto
+ * imagenesVariante:
+ * type: array
+ * items:
+ * type: string
+ * format: binary
+ * description: Imágenes asociadas a cada variante del producto
+ * responses:
+ * 200:
+ * description: Producto creado correctamente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Producto creado correctamente
+ * 400:
+ * description: Error en los parámetros proporcionados
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Los parámetros proporcionados no son válidos
+ * 401:
+ * description: No autorizado, token inválido o falta de permisos
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No tiene permisos para realizar esta acción
+ * 500:
+ * description: Error interno del servidor
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error al crear producto
+ * error:
+ * type: string
+ * example: Error al crear variante
+ */
+
+ruteador.post(
+ RUTAS.PRODUCTOS.CREAR,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CREAR_PRODUCTO),
+ controlador.crearProducto
+);
+
+module.exports = ruteador;
diff --git a/Productos/Rutas/RutasIndividuales/eliminarProducto.routes.js b/Productos/Rutas/RutasIndividuales/eliminarProducto.routes.js
new file mode 100644
index 00000000..263b9f2e
--- /dev/null
+++ b/Productos/Rutas/RutasIndividuales/eliminarProducto.routes.js
@@ -0,0 +1,55 @@
+// RF[30] Eliminar Producto - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF30]
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/pro/ctrl/eliminarProducto.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * RF[30] Eliminar Producto - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF30]
+ *
+ * @swagger
+ * /api/productos/eliminar:
+ * delete:
+ * summary: Eliminar uno o varios productos
+ * tags: [Productos]
+ * security:
+ * - ApiKeyAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * ids:
+ * type: array
+ * items:
+ * type: integer
+ * example: [1, 2, 3]
+ * responses:
+ * 200:
+ * description: Productos eliminados exitosamente
+ * 400:
+ * description: Error al eliminar los productos
+ * 401:
+ * description: No autorizado
+ * 500:
+ * description: Error interno del servidor
+ */
+ruteador.delete(
+ RUTAS.PRODUCTOS.ELIMINAR_PRODUCTO,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.ELIMINAR_PRODUCTO),
+ controlador.eliminarProductoController
+);
+
+module.exports = ruteador;
diff --git a/Productos/Rutas/RutasIndividuales/exportarProductos.routes.js b/Productos/Rutas/RutasIndividuales/exportarProductos.routes.js
new file mode 100644
index 00000000..5fde8376
--- /dev/null
+++ b/Productos/Rutas/RutasIndividuales/exportarProductos.routes.js
@@ -0,0 +1,77 @@
+//RF58 - Exportar Productos - https://codeandco-wiki.netlify.app/docs/next/proyectos/textiles/documentacion/requisitos/RF58
+
+/**
+ * @swagger
+ * /api/productos/exportar:
+ * post:
+ * summary: Exporta la lista completa de empleados en formato CSV.
+ * tags:
+ * - Productos
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * parameters:
+ * - in: header
+ * name: x-api-key
+ * required: true
+ * schema:
+ * type: string
+ * description: Clave de API
+ * - in: header
+ * name: Authorization
+ * required: true
+ * schema:
+ * type: string
+ * description: Token JWT con formato "Bearer "
+ * responses:
+ * 200:
+ * description: Archivo CSV generado correctamente.
+ * content:
+ * text/csv:
+ * schema:
+ * type: string
+ * format: binary
+ * 204:
+ * description: No hay productos para exportar.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No hay productos para exportar.
+ * 400:
+ * description: Error interno del servidor al exportar productos.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error al exportar la lista de productos.
+ */
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/pro/ctrl/exportarProductos.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+ruteador.post(
+ RUTAS.PRODUCTOS.EXPORTAR_PRODUCTOS,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ validarYSanitizar,
+ verificarPermisos(PERMISOS.EXPORTAR_PRODUCTOS),
+ controlador.exportarProductos
+);
+
+module.exports = ruteador;
diff --git a/Productos/Rutas/RutasIndividuales/importarProductos.routes.js b/Productos/Rutas/RutasIndividuales/importarProductos.routes.js
new file mode 100644
index 00000000..2c95b954
--- /dev/null
+++ b/Productos/Rutas/RutasIndividuales/importarProductos.routes.js
@@ -0,0 +1,191 @@
+// RF[56] Leer producto - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF56]
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/pro/ctrl/importarProductos.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/productos/importar-productos:
+ * post:
+ * summary: Importa un lote de productos con variantes y opciones desde un archivo procesado.
+ * tags:
+ * - Productos
+ * security:
+ * - bearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: array
+ * items:
+ * type: object
+ * required:
+ * - producto
+ * - variantes
+ * properties:
+ * producto:
+ * type: object
+ * properties:
+ * idProveedor:
+ * type: integer
+ * nullable: true
+ * example: 12
+ * nombreComun:
+ * type: string
+ * example: Tornillo galvanizado
+ * nombreComercial:
+ * type: string
+ * nullable: true
+ * example: Tornillo FG 3/4
+ * descripcion:
+ * type: string
+ * nullable: true
+ * example: Tornillo de acero inoxidable
+ * marca:
+ * type: string
+ * nullable: true
+ * example: TRUPER
+ * modelo:
+ * type: string
+ * nullable: true
+ * example: M3X40
+ * tipoProducto:
+ * type: string
+ * nullable: true
+ * example: Ferretería
+ * costo:
+ * type: number
+ * example: 3.5
+ * precioVenta:
+ * type: number
+ * example: 5.0
+ * precioCliente:
+ * type: number
+ * example: 4.5
+ * precioPuntos:
+ * type: number
+ * example: 4.0
+ * impuesto:
+ * type: number
+ * example: 0.16
+ * descuento:
+ * type: number
+ * example: 0.1
+ * estado:
+ * type: integer
+ * enum: [0, 1]
+ * example: 1
+ * envio:
+ * type: integer
+ * enum: [0, 1]
+ * example: 1
+ * variantes:
+ * type: array
+ * items:
+ * type: object
+ * required:
+ * - nombreVariante
+ * - opciones
+ * properties:
+ * nombreVariante:
+ * type: string
+ * example: Color
+ * descripcion:
+ * type: string
+ * nullable: true
+ * example: Variantes por color
+ * opciones:
+ * type: array
+ * items:
+ * type: object
+ * required:
+ * - cantidad
+ * - valorOpcion
+ * - SKUautomatico
+ * - SKUcomercial
+ * - costoAdicional
+ * - descuento
+ * - estado
+ * properties:
+ * cantidad:
+ * type: integer
+ * example: 10
+ * valorOpcion:
+ * type: string
+ * example: Rojo
+ * SKUautomatico:
+ * type: string
+ * example: SKU-AUTO-1
+ * SKUcomercial:
+ * type: string
+ * example: SKU-ROJO-123
+ * costoAdicional:
+ * type: number
+ * example: 0.5
+ * descuento:
+ * type: number
+ * example: 10
+ * estado:
+ * type: integer
+ * enum: [0, 1]
+ * example: 1
+ * responses:
+ * 200:
+ * description: Importación completada exitosamente o con errores parciales.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Importación completada exitosamente.
+ * errores:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * fila:
+ * type: integer
+ * example: 3
+ * error:
+ * type: string
+ * example: Producto sin variantes válidas.
+ * 400:
+ * description: No se recibieron productos válidos.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No se recibieron productos válidos.
+ * 401:
+ * description: No autorizado. Token inválido o faltante.
+ * 403:
+ * description: Acceso denegado por falta de permisos.
+ * 500:
+ * description: Error interno del servidor.
+ */
+
+ruteador.post(
+ RUTAS.PRODUCTOS.IMPORTAR,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ validarYSanitizar,
+ verificarPermisos(PERMISOS.IMPORTAR_PRODUCTOS),
+ controlador.importarProductos
+);
+
+module.exports = ruteador;
diff --git a/Productos/Rutas/RutasIndividuales/leerProductos.routes.js b/Productos/Rutas/RutasIndividuales/leerProductos.routes.js
new file mode 100644
index 00000000..d11e4424
--- /dev/null
+++ b/Productos/Rutas/RutasIndividuales/leerProductos.routes.js
@@ -0,0 +1,14 @@
+const express = require('express');
+const ruteador = express.Router();
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const controlador = require('@altertex/pro/ctrl/leerProducto.controller');
+// RF[28] Leer producto - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF28]
+
+ruteador.get(RUTAS.PRODUCTOS.LEER, revisarApiKey(), autorizarToken, verificarPermisos(PERMISOS.LEER_PRODUCTO), validarYSanitizar, controlador.leerProducto);
+
+module.exports = ruteador;
\ No newline at end of file
diff --git a/Productos/Rutas/indexProductos.routes.js b/Productos/Rutas/indexProductos.routes.js
new file mode 100644
index 00000000..3f014e4e
--- /dev/null
+++ b/Productos/Rutas/indexProductos.routes.js
@@ -0,0 +1,25 @@
+const express = require('express');
+const ruteador = express.Router();
+const rutaConsultarLista = require('@altertex/pro/rutasInd/consultarProductos.routes');
+const rutaEliminar = require('@altertex/pro/rutasInd/eliminarProducto.routes');
+const rutaCrearProducto = require('@altertex/pro/rutasInd/crearProducto.routes');
+const rutaImportarProductos = require('@altertex/pro/rutasInd/importarProductos.routes');
+const rutasLeerProducto = require('@altertex/pro/rutasInd/leerProductos.routes');
+const rutasExportarProductos = require('@altertex/pro/rutasInd/exportarProductos.routes');
+
+const RUTAS = require('@altertex/util/const/rutas');
+
+//RF27 Consulta Lista de Productos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF27
+ruteador.use(RUTAS.PRODUCTOS.BASE, rutaConsultarLista);
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+ruteador.use(RUTAS.PRODUCTOS.BASE, rutaCrearProducto);
+// RF[30] Eliminar Producto - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF30]
+ruteador.use(RUTAS.PRODUCTOS.BASE, rutaEliminar);
+// RF[28] Leer producto - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF28]
+ruteador.use(RUTAS.PRODUCTOS.BASE, rutasLeerProducto);
+// RF[56] Leer producto - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF56]
+ruteador.use(RUTAS.PRODUCTOS.BASE, rutaImportarProductos);
+// RF[58] Exportar Productos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF58]
+ruteador.use(RUTAS.PRODUCTOS.BASE, rutasExportarProductos);
+
+module.exports = ruteador;
diff --git a/Proveedores/Controladores/consultarProveedores.controller.js b/Proveedores/Controladores/consultarProveedores.controller.js
new file mode 100644
index 00000000..418c9b02
--- /dev/null
+++ b/Proveedores/Controladores/consultarProveedores.controller.js
@@ -0,0 +1,51 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+const repositorio = require('@altertex/prove/repos/repositorioConsultarProveedores');
+const MENSAJES_PROVEEDORES = require('@altertex/util/const/mensajesProveedores');
+
+/**
+ * Controlador para la consulta de la lista de proveedores de un cliente.
+ *
+ * @async
+ * @function consultarLista
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.user - Datos del usuario autenticado.
+ * @param {number} req.user.clienteSeleccionado - ID del cliente seleccionado para la consulta.
+ * @param {object} res - Objeto de respuesta de Express.
+ *
+ * @returns {Response} Respuesta HTTP con estado:
+ * - 200 si la consulta es exitosa, junto con los datos de los proveedores.
+ * - 204 si no hay proveedores registrados.
+ * - 400 si los parámetros proporcionados son inválidos.
+ * - 500 si ocurre un error en el servidor.
+ *
+ * @throws {Error} Si ocurre un error inesperado durante la operación.
+ */
+exports.consultarLista = async (req, res) => {
+ const idCliente = parseInt(req.user?.clienteSeleccionado);
+
+ if (!idCliente || isNaN(idCliente)) {
+ return res.status(MENSAJES_PROVEEDORES.DATOS_PROVEEDOR_INVALIDOS.codigo).json({
+ mensaje: MENSAJES_PROVEEDORES.DATOS_PROVEEDOR_INVALIDOS.mensaje,
+ });
+ }
+
+ try {
+ const resultados = await repositorio.obtenerProveedores(idCliente);
+
+ if (!resultados || resultados.length === 0) {
+ return res.status(MENSAJES_PROVEEDORES.LISTA_PROVEEDORES_VACIA.codigo).json({
+ mensaje: MENSAJES_PROVEEDORES.LISTA_PROVEEDORES_VACIA.mensaje,
+ });
+ }
+
+ return res.status(MENSAJES_PROVEEDORES.CONSULTA_PROVEEDORES_EXITOSA.codigo).json({
+ mensaje: MENSAJES_PROVEEDORES.CONSULTA_PROVEEDORES_EXITOSA.mensaje,
+ listaProveedores: resultados,
+ });
+ } catch (error) {
+ console.error('Error al consultar proveedores:', error);
+ return res.status(MENSAJES_PROVEEDORES.ERROR_CONSULTAR_PROVEEDORES.codigo).json({
+ mensaje: MENSAJES_PROVEEDORES.ERROR_CONSULTAR_PROVEEDORES.mensaje,
+ });
+ }
+};
diff --git a/Proveedores/Controladores/crearProveedor.controller.js b/Proveedores/Controladores/crearProveedor.controller.js
new file mode 100644
index 00000000..7d8a70ef
--- /dev/null
+++ b/Proveedores/Controladores/crearProveedor.controller.js
@@ -0,0 +1,48 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+const validarProveedor = require('@altertex/util/vali/validarProveedor');
+const repositorioCrearProveedor = require('@altertex/prove/repos/repositorioCrearProvedor');
+const MENSAJES_PROVEEDORES = require('@altertex/util/const/mensajesProveedores');
+
+/**
+ * Controlador para crear un proveedor de forma independiente.
+ *
+ * @async
+ * @function crearProveedor
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.body - Cuerpo de la solicitud HTTP.
+ * @param {object} res - Objeto de respuesta de Express.
+ *
+ * @returns {Response} Respuesta HTTP con estado:
+ * - 200 si la creación es exitosa, junto con el ID del proveedor.
+ * - 400 si los parámetros proporcionados son inválidos.
+ * - 500 si ocurre un error en el servidor.
+ */
+exports.crearProveedor = async (req, res) => {
+ const proveedor = req.body;
+ const idCliente = parseInt(req.user.clienteSeleccionado);
+
+ const errorProveedor = validarProveedor(proveedor);
+ if (errorProveedor) {
+ return res.status(MENSAJES_PROVEEDORES.DATOS_PROVEEDOR_INVALIDOS.codigo).json({
+ mensaje: MENSAJES_PROVEEDORES.DATOS_PROVEEDOR_INVALIDOS.mensaje,
+ });
+ }
+
+ try {
+ const idProveedor = await repositorioCrearProveedor.crearProveedor(idCliente, proveedor);
+
+ if (!idProveedor) {
+ throw new Error('Error al crear proveedor');
+ }
+
+ return res.status(MENSAJES_PROVEEDORES.PROVEEDOR_CREADO_EXITOSAMENTE.codigo).json({
+ mensaje: MENSAJES_PROVEEDORES.PROVEEDOR_CREADO_EXITOSAMENTE.mensaje,
+ });
+ } catch (error) {
+ console.error('Error al crear proveedor:', error);
+ return res.status(MENSAJES_PROVEEDORES.ERROR_CREAR_PROVEEDOR.codigo).json({
+ mensaje: MENSAJES_PROVEEDORES.ERROR_CREAR_PROVEEDOR.mensaje,
+ error: error.message,
+ });
+ }
+};
diff --git a/Proveedores/Datos/Repositorios/repositorioConsultarProveedores.js b/Proveedores/Datos/Repositorios/repositorioConsultarProveedores.js
new file mode 100644
index 00000000..9f1ea2df
--- /dev/null
+++ b/Proveedores/Datos/Repositorios/repositorioConsultarProveedores.js
@@ -0,0 +1,25 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const consultas = require('@altertex/util/const/consultasProveedores');
+
+/**
+ * Obtiene la lista de proveedores registrados para un cliente específico.
+ *
+ * Esta función ejecuta una consulta SQL para recuperar los proveedores asociados
+ * al cliente proporcionado. Devuelve un arreglo de proveedores si la operación
+ * es exitosa, o un arreglo vacío en caso de error.
+ *
+ * @param {string|number} clienteSeleccionado - ID o identificador del cliente del cual se quieren obtener los proveedores.
+ *
+ * @returns {Promise} Un arreglo de objetos que representan los proveedores, o un arreglo vacío si ocurre un error.
+ */
+exports.obtenerProveedores = async (clienteSeleccionado) => {
+ const query = consultas.OBTENER_LISTA;
+ try {
+ const resultados = await correrQuery(query, [clienteSeleccionado]);
+ return resultados;
+ } catch (error) {
+ console.error('Error al obtener los proveedores:', error);
+ return [];
+ }
+};
diff --git a/Proveedores/Datos/Repositorios/repositorioCrearProvedor.js b/Proveedores/Datos/Repositorios/repositorioCrearProvedor.js
new file mode 100644
index 00000000..cc674bb4
--- /dev/null
+++ b/Proveedores/Datos/Repositorios/repositorioCrearProvedor.js
@@ -0,0 +1,46 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const consultas = require('@altertex/util/const/consultasProveedores');
+
+/**
+ * Crea un nuevo proveedor en la base de datos.
+ *
+ * Esta función ejecuta una consulta SQL para insertar los datos de un proveedor
+ * utilizando los parámetros proporcionados. Devuelve el ID del proveedor recién creado
+ * en caso de éxito, o un array vacío si ocurre algún error durante la operación.
+ *
+ * @param {string|number} clienteSeleccionado - ID o identificador del cliente del cual se quieren obtener los proveedores.
+ * @param {object} proveedor - Objeto que contiene la información del proveedor.
+ * @param {string} proveedor.nombre - Nombre del contacto del proveedor.
+ * @param {string} proveedor.nombreCompania - Nombre de la compañía del proveedor.
+ * @param {string} proveedor.telefonoContacto - Teléfono de contacto del proveedor.
+ * @param {string} proveedor.direccion - Dirección del proveedor.
+ * @param {string} proveedor.codigoPostal - Código postal de la dirección del proveedor.
+ * @param {string} proveedor.pais - País del proveedor.
+ * @param {string} proveedor.estado - Estado o provincia del proveedor.
+ *
+ * @returns {Promise} El ID del proveedor recién creado en caso de éxito, o un arreglo vacío en caso de error.
+ */
+exports.crearProveedor = async (clienteSeleccionado, proveedor) => {
+ const query = consultas.CREAR;
+ const parametros = [
+ clienteSeleccionado,
+ proveedor.nombre,
+ proveedor.nombreCompania,
+ proveedor.telefonoContacto,
+ proveedor.direccion,
+ proveedor.codigoPostal,
+ proveedor.pais,
+ proveedor.estado,
+ ];
+
+ try {
+ const resultados = await correrQuery(query, parametros);
+
+ const idProveedor = resultados.insertId;
+ return idProveedor;
+ } catch (error) {
+ console.error('Error al crear proveedor:', error);
+ return [];
+ }
+};
diff --git a/Proveedores/Rutas/RutasIndividuales/consultarProveedores.routes.js b/Proveedores/Rutas/RutasIndividuales/consultarProveedores.routes.js
new file mode 100644
index 00000000..c520bf2c
--- /dev/null
+++ b/Proveedores/Rutas/RutasIndividuales/consultarProveedores.routes.js
@@ -0,0 +1,129 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/prove/ctrl/consultarProveedores.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/proveedores/consultar-lista:
+ * post:
+ * summary: Consultar lista de proveedores
+ * description: Obtiene la lista de proveedores asociados al cliente seleccionado
+ * tags: [Proveedores]
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: false
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * example: {}
+ * responses:
+ * 200:
+ * description: Consulta exitosa
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Consulta de proveedores exitosa
+ * listaProveedores:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * id:
+ * type: integer
+ * example: 1
+ * nombre:
+ * type: string
+ * example: Juan Pérez
+ * nombreCompania:
+ * type: string
+ * example: Textiles del Norte S.A.
+ * telefonoContacto:
+ * type: string
+ * example: +52 55 1234 5678
+ * correoContacto:
+ * type: string
+ * example: juan.perez@textilesnorte.com
+ * direccion:
+ * type: string
+ * example: Av. Industrial 123, Col. Centro
+ * codigoPostal:
+ * type: string
+ * example: 12345
+ * pais:
+ * type: string
+ * example: México
+ * estado:
+ * type: integer
+ * example: 1
+ * fechaCreacion:
+ * type: string
+ * format: date-time
+ * example: 2023-10-15T14:30:00Z
+ * 204:
+ * description: No hay proveedores registrados
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No hay proveedores registrados
+ * 400:
+ * description: Parámetros inválidos
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Los datos del proveedor son inválidos
+ * 401:
+ * description: No autorizado, token inválido o falta de permisos
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No tiene permisos para realizar esta acción
+ * 500:
+ * description: Error interno del servidor
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error al consultar proveedores
+ */
+
+ruteador.post(
+ RUTAS.PROVEEDORES.CONSULTAR_LISTA,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CONSULTAR_PRODUCTOS),
+ controlador.consultarLista
+);
+
+module.exports = ruteador;
diff --git a/Proveedores/Rutas/RutasIndividuales/crearProveedor.routes.js b/Proveedores/Rutas/RutasIndividuales/crearProveedor.routes.js
new file mode 100644
index 00000000..944fe067
--- /dev/null
+++ b/Proveedores/Rutas/RutasIndividuales/crearProveedor.routes.js
@@ -0,0 +1,128 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/prove/ctrl/crearProveedor.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/proveedores/crear:
+ * post:
+ * summary: Crear un nuevo proveedor
+ * description: Crea un nuevo proveedor asociado al cliente seleccionado
+ * tags: [Proveedores]
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * required:
+ * - nombre
+ * - nombreCompania
+ * - telefonoContacto
+ * - correoContacto
+ * - direccion
+ * - codigoPostal
+ * - pais
+ * - estado
+ * properties:
+ * nombre:
+ * type: string
+ * description: Nombre del contacto del proveedor
+ * example: Juan Pérez
+ * nombreCompania:
+ * type: string
+ * description: Nombre de la compañía del proveedor
+ * example: Textiles del Norte S.A.
+ * telefonoContacto:
+ * type: string
+ * description: Número telefónico de contacto
+ * example: +52 55 1234 5678
+ * correoContacto:
+ * type: string
+ * description: Correo electrónico de contacto
+ * example: juan.perez@textilesnorte.com
+ * direccion:
+ * type: string
+ * description: Dirección física del proveedor
+ * example: Av. Industrial 123, Col. Centro
+ * codigoPostal:
+ * type: string
+ * description: Código postal de la dirección
+ * example: 12345
+ * pais:
+ * type: string
+ * description: País donde se encuentra el proveedor
+ * example: México
+ * estado:
+ * type: number
+ * description: Estado del proveedor (1 activo, 0 inactivo)
+ * enum: [0, 1]
+ * example: 1
+ * responses:
+ * 200:
+ * description: Proveedor creado exitosamente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Proveedor creado exitosamente
+ * 400:
+ * description: Datos del proveedor inválidos
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Los datos del proveedor son inválidos
+ * 401:
+ * description: No autorizado, token inválido o falta de permisos
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No tiene permisos para realizar esta acción
+ * 500:
+ * description: Error interno del servidor
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error al crear proveedor
+ * error:
+ * type: string
+ * example: Error al crear proveedor
+ */
+
+ruteador.post(
+ RUTAS.PROVEEDORES.CREAR,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CREAR_PRODUCTO),
+ controlador.crearProveedor
+);
+
+module.exports = ruteador;
diff --git a/Proveedores/Rutas/indexProveedores.routes.js b/Proveedores/Rutas/indexProveedores.routes.js
new file mode 100644
index 00000000..f464092b
--- /dev/null
+++ b/Proveedores/Rutas/indexProveedores.routes.js
@@ -0,0 +1,13 @@
+const express = require('express');
+const ruteador = express.Router();
+const rutaConsultarLista = require('@altertex/prove/rutasInd/consultarProveedores.routes');
+const rutaCrearProveedor = require('@altertex/prove/rutasInd/crearProveedor.routes');
+
+const RUTAS = require('@altertex/util/const/rutas');
+
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+ruteador.use(RUTAS.PROVEEDORES.BASE, rutaConsultarLista);
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+ruteador.use(RUTAS.PROVEEDORES.BASE, rutaCrearProveedor);
+
+module.exports = ruteador;
diff --git a/Roles/Controladores/actualizarRol.controller.js b/Roles/Controladores/actualizarRol.controller.js
new file mode 100644
index 00000000..0e129abb
--- /dev/null
+++ b/Roles/Controladores/actualizarRol.controller.js
@@ -0,0 +1,29 @@
+const MENSAJES = require('@altertex/util/const/mensajesRoles');
+const repositorio = require('@altertex/rol/repos/repositorioActualizarRol');
+
+/**
+ * Controlador para actualizar un rol.
+ *
+ * Este controlador recibe los datos del rol a actualizar desde el cuerpo de la solicitud
+ * y el cliente seleccionado desde el usuario autenticado. Valida los datos y delega
+ * la lógica de actualización al repositorio.
+ *
+ * @function
+ * @param {Express.Request} req - Objeto de solicitud de Express.
+ * @param {Express.Response} res - Objeto de respuesta de Express.
+ * @returns {Promise} - Retorna una respuesta HTTP con el resultado de la operación.
+ */
+exports.actualizarRol = async (req, res) => {
+ const datosActualizacion = req.body.datosRolActualizacion;
+
+ if (!datosActualizacion) {
+ return res.status(MENSAJES.PARAMETROS_INVALIDOS.codigo).json({ mensaje: MENSAJES.PARAMETROS_INVALIDOS.mensaje });
+ }
+
+ try {
+ await repositorio.actualizarRol(datosActualizacion);
+ return res.status(MENSAJES.ACTUALIZAR_ROL.codigo).json({ mensaje: MENSAJES.ACTUALIZAR_ROL.mensaje });
+ } catch (error) {
+ return res.status(400).json({ mensaje: error.message });
+ }
+};
\ No newline at end of file
diff --git a/Roles/Controladores/consultarDetalleRol.controller.js b/Roles/Controladores/consultarDetalleRol.controller.js
new file mode 100644
index 00000000..a402fe08
--- /dev/null
+++ b/Roles/Controladores/consultarDetalleRol.controller.js
@@ -0,0 +1,69 @@
+const repositorio = require('@altertex/rol/repos/repositorioDetalleRol');
+const MENSAJES_ROLES = require('@altertex/util/const/mensajesRoles');
+
+/**
+ * RF8 - Leer rol
+ * Documentación del requisito funcional:
+ * https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF8
+ *
+ * @function consultarDetalle
+ * @async
+ * @param {object} req - Objeto de solicitud HTTP (Request).
+ * @param {object} res - Objeto de respuesta HTTP (Response).
+ * @returns {Response} Respuesta HTTP con los detalles del rol solicitado.
+ *
+ * @description
+ * Este controlador obtiene el detalle de un rol: nombre, descripción,
+ * número de usuarios asociados y permisos relacionados.
+ */
+exports.consultarDetalle = async (req, res) => {
+ try {
+ const { idRol } = req.query;
+
+ // Validación: verificar que se proporcione un ID válido
+ if (!idRol || isNaN(Number(idRol))) {
+ return res
+ .status(MENSAJES_ROLES.PARAMETROS_INVALIDOS.codigo)
+ .json({ mensaje: MENSAJES_ROLES.PARAMETROS_INVALIDOS.mensaje });
+ }
+
+ // Se consulta al repositorio de roles para obtener el detalle por ID.
+ const resultado = await repositorio.obtenerDetalleRol(Number(idRol));
+
+ // Validación: si no se encontró el rol, se responde con mensaje de "sin resultados".
+ if (!resultado || resultado.length === 0) {
+ return res
+ .status(MENSAJES_ROLES.SIN_RESULTADOS.codigo)
+ .json({ mensaje: MENSAJES_ROLES.SIN_RESULTADOS.mensaje });
+ }
+
+ // Extrae los datos generales del rol desde la primera fila
+ const { nombreRol, descripcionRol, totalUsuarios } = resultado[0];
+
+ // Construye arreglo de permisos (omite si no tiene permisos)
+ const permisos = resultado
+ .filter(permiso => permiso.idPermiso !== null)
+ .map(permiso => ({
+ id: permiso.idPermiso,
+ nombre: permiso.nombrePermiso,
+ descripcion: permiso.descripcionPermiso,
+ }));
+
+ // Respuesta exitosa con datos
+ return res.status(MENSAJES_ROLES.CONSULTA_EXITOSA.codigo).json({
+ mensaje: MENSAJES_ROLES.CONSULTA_EXITOSA.mensaje,
+ rol: {
+ idRol: Number(idRol),
+ nombre: nombreRol,
+ descripcion: descripcionRol,
+ totalUsuarios,
+ permisos,
+ },
+ });
+ } catch {
+ // Error inesperado en el servidor
+ return res
+ .status(MENSAJES_ROLES.ERROR_CONSULTAR_ROLES.codigo)
+ .json({ mensaje: MENSAJES_ROLES.ERROR_CONSULTAR_ROLES.mensaje });
+ }
+};
\ No newline at end of file
diff --git a/Roles/Controladores/consultarLista.controller.js b/Roles/Controladores/consultarLista.controller.js
new file mode 100644
index 00000000..0245c902
--- /dev/null
+++ b/Roles/Controladores/consultarLista.controller.js
@@ -0,0 +1,44 @@
+// Importación del repositorio de roles y los mensajes constantes relacionados a la funcionalidad de roles.
+const repositorio = require('@altertex/rol/repos/repositorioRoles');
+const MENSAJES_ROLES = require('@altertex/util/const/mensajesRoles');
+
+/**
+ * Controlador para consultar la lista de roles.
+ *
+ * @function consultarLista
+ * @async
+ * @param {object} req - Objeto de solicitud HTTP (Request).
+ * @param {object} res - Objeto de respuesta HTTP (Response).
+ * @returns {Response} Respuesta HTTP con el resultado de la consulta.
+ *
+ * @description
+ * Este controlador realiza una consulta al repositorio de roles para obtener
+ * la lista completa. Si no se encuentran resultados, responde con el código y mensaje
+ * correspondiente a resultados vacíos. En caso de éxito, devuelve la lista con un mensaje
+ * de éxito. Ante cualquier error inesperado, devuelve un error 500.
+ */
+exports.consultarLista = async (req, res) => {
+ try {
+ // Se consulta al repositorio de roles para obtener todos los registros.
+ const resultados = await repositorio.obtenerRoles();
+
+
+ // Validación: si no se encontraron resultados, se responde con el mensaje de "sin resultados".
+ if (!resultados || resultados.length === 0) {
+ return res
+ .status(MENSAJES_ROLES.SIN_RESULTADOS.codigo)
+ .json({ mensaje: MENSAJES_ROLES.SIN_RESULTADOS.mensaje });
+ }
+
+ // En caso de éxito, se responde con el mensaje correspondiente y los datos encontrados.
+ return res.status(MENSAJES_ROLES.CONSULTA_EXITOSA.codigo).json({
+ mensaje: MENSAJES_ROLES.CONSULTA_EXITOSA.mensaje,
+ roles: resultados,
+ });
+ } catch {
+ // Manejo de errores inesperados, con log en consola para facilitar el diagnóstico.
+
+ // Se responde con un error 500 y un mensaje genérico para el cliente.
+ return res.status(500).json({ mensaje: 'Error al consultar roles' });
+ }
+};
diff --git a/Roles/Controladores/crearRol.controller.js b/Roles/Controladores/crearRol.controller.js
new file mode 100644
index 00000000..bdec2217
--- /dev/null
+++ b/Roles/Controladores/crearRol.controller.js
@@ -0,0 +1,62 @@
+const repositorio = require('@altertex/rol/repos/repositorioCrearRol');
+const MENSAJES = require('@altertex/util/const/mensajesRoles');
+
+/**
+ * Controlador para crear un nuevo rol.
+ *
+ * Este controlador realiza las siguientes validaciones y operaciones:
+ * - Verifica que el nombre del rol sea válido.
+ * - Verifica que los permisos sean un arreglo no vacío.
+ * - Valida que el nombre del rol no esté duplicado en la base de datos.
+ * - Valida que todos los IDs de permisos proporcionados existan en la base de datos.
+ * - Inserta el rol y asocia los permisos si todas las validaciones son exitosas.
+ *
+ * @async
+ * @function crearRol
+ * @param {Express.Request} req - Objeto de solicitud HTTP. Se espera que el cuerpo (`req.body`) contenga:
+ * @param {string} req.body.nombre - Nombre del rol a crear.
+ * @param {string} [req.body.descripcion] - Descripción opcional del rol.
+ * @param {number[]} req.body.permisos - Lista de IDs de permisos a asociar.
+ * @param {Express.Response} res - Objeto de respuesta HTTP.
+ * @returns {Promise} - Respuesta JSON con el estado de la creación del rol.
+ */
+exports.crearRol = async (req, res) => {
+ const { nombre, descripcion, permisos } = req.body;
+
+ // Validación del nombre del rol
+ if (!nombre || typeof nombre !== 'string') {
+ return res.status(400).json({ mensaje: MENSAJES.NOMBRE_OBLIGATORIO });
+ }
+
+ // Validación de los permisos
+ if (!Array.isArray(permisos) || permisos.length === 0) {
+ return res.status(400).json({ mensaje: MENSAJES.PERMISOS_OBLIGATORIOS });
+ }
+
+ try {
+ // Verificar si el nombre del rol ya existe
+ const existe = await repositorio.verificarNombreRol(nombre);
+ if (existe) {
+ return res.status(400).json({ mensaje: MENSAJES.ROL_EXISTENTE });
+ }
+
+ // Verificar que todos los permisos sean válidos
+ for (const idPermiso of permisos) {
+ const valido = await repositorio.verificarPermiso(idPermiso);
+ if (!valido) {
+ return res.status(400).json({ mensaje: MENSAJES.PERMISO_INVALIDO(idPermiso) });
+ }
+ }
+
+ // Crear el rol y asociar los permisos
+ const resultado = await repositorio.crearRol(nombre, descripcion);
+ if (resultado.insertId) {
+ await repositorio.asociarPermisosARol(resultado.insertId, permisos);
+ return res.status(201).json({ mensaje: MENSAJES.ROL_CREADO });
+ } else {
+ return res.status(400).json({ mensaje: MENSAJES.ERROR_CREACION });
+ }
+ } catch {
+ return res.status(500).json({ mensaje: MENSAJES.ERROR_CREACION });
+ }
+};
diff --git a/Roles/Controladores/eliminarRol.controller.js b/Roles/Controladores/eliminarRol.controller.js
new file mode 100644
index 00000000..3d7a2d59
--- /dev/null
+++ b/Roles/Controladores/eliminarRol.controller.js
@@ -0,0 +1,30 @@
+const MENSAJES = require('@altertex/util/const/mensajesRoles');
+const repositorio = require('@altertex/rol/repos/repositoriorEliminar');
+// RF10 - Eliminar rol - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF10
+
+/**
+ * Controlador para eliminar un rol existente.
+ *
+ * @async
+ * @function eliminarRol
+ * @param {Express.Request} req - Objeto de solicitud de Express, debe contener `idRol` en `req.body`.
+ * @param {Express.Response} res - Objeto de respuesta de Express.
+ * @returns {Promise} - No retorna un valor, responde al cliente con un JSON indicando éxito o error.
+ *
+ * @description
+ * Esta función intenta eliminar un rol utilizando el repositorio correspondiente.
+ * Si la eliminación es exitosa, responde con un código 200 y un mensaje de éxito.
+ * Si ocurre un error, responde con un código 400 y un mensaje de error.
+ */
+exports.eliminarRol = async (req, res) => {
+ const idRol = req.body.idsRol;
+ try {
+ await repositorio.eliminarRol(idRol);
+ return res
+ .status(MENSAJES.ELIMINAR_ROL_EXITO.codigo)
+ .json({ mensaje: MENSAJES.ELIMINAR_ROL_EXITO.mensaje });
+ } catch (error) {
+ const mensaje = error.message || MENSAJES.ELIMINAR_ROL_ERROR.mensaje;
+ return res.status(400).json({ mensaje });
+ }
+};
diff --git a/Roles/Controladores/obtenerOpcionesRol.controller.js b/Roles/Controladores/obtenerOpcionesRol.controller.js
new file mode 100644
index 00000000..46705bbe
--- /dev/null
+++ b/Roles/Controladores/obtenerOpcionesRol.controller.js
@@ -0,0 +1,28 @@
+const repositorio = require('@altertex/rol/repos/obtenerOpcionesRolRepositorio');
+const MENSAJES = require('@altertex/util/const/mensajesRoles');
+
+/**
+ * Controlador para obtener la lista de permisos disponibles para asociar a un rol.
+ *
+ * Este endpoint se utiliza generalmente cuando se va a crear o editar un rol,
+ * y se necesita mostrar las opciones de permisos disponibles en el sistema.
+ *
+ * @async
+ * @function obtenerOpcionesRol
+ * @param {Express.Request} req - Objeto de solicitud HTTP (no se espera ningún parámetro específico).
+ * @param {Express.Response} res - Objeto de respuesta HTTP.
+ * @returns {Promise} Devuelve una respuesta JSON con el estado y la lista de permisos.
+ */
+exports.obtenerOpcionesRol = async (req, res) => {
+ try {
+ const resultado = await repositorio.obtenerPermisos();
+ return res.status(200).json({
+ mensaje: MENSAJES.PERMISOS_OBTENIDOS,
+ resultado,
+ });
+ } catch {
+ return res.status(500).json({
+ mensaje: MENSAJES.ERROR_OBTENIENDO_PERMISOS,
+ });
+ }
+};
diff --git a/Roles/Datos/Repositorios/obtenerOpcionesRolRepositorio.js b/Roles/Datos/Repositorios/obtenerOpcionesRolRepositorio.js
new file mode 100644
index 00000000..74110abf
--- /dev/null
+++ b/Roles/Datos/Repositorios/obtenerOpcionesRolRepositorio.js
@@ -0,0 +1,13 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+
+/**
+ * Obtiene la lista de permisos disponibles desde la base de datos.
+ *
+ * @async
+ * @function obtenerPermisos
+ * @returns {Promise>} Arreglo de objetos con los permisos disponibles.
+ */
+exports.obtenerPermisos = async () => {
+ const consulta = 'SELECT idPermiso AS id, nombre FROM permiso';
+ return await correrQuery(consulta);
+};
diff --git a/Roles/Datos/Repositorios/repositorioActualizarRol.js b/Roles/Datos/Repositorios/repositorioActualizarRol.js
new file mode 100644
index 00000000..22e67561
--- /dev/null
+++ b/Roles/Datos/Repositorios/repositorioActualizarRol.js
@@ -0,0 +1,94 @@
+const MENSAJES = require('@altertex/util/const/mensajesRoles');
+const conexion = require('@altertex/util/bd/db');
+
+/**
+ * Actualiza un rol existente, incluyendo su nombre, descripción y permisos asociados.
+ *
+ * @param {object} datosActualizarRol - Datos necesarios para actualizar el rol.
+ * @param {object} datosActualizarRol.datosRol - Contiene el nombre, descripción y permisos del rol.
+ * @param {number} datosActualizarRol.idRol - ID del rol a actualizar.
+ * @throws {Error} Si hay parámetros inválidos o errores en la base de datos.
+ */
+exports.actualizarRol = async (datosActualizarRol) => {
+ const datosRol = datosActualizarRol.datosRol;
+ const idRol = datosActualizarRol.idRol;
+ const permisos = datosRol.permisos || [];
+
+ if (!datosActualizarRol || !idRol) {
+ throw new Error(MENSAJES.PARAMETROS_INVALIDOS.mensaje);
+ }
+
+ const conexionBD = await conexion.getConnection();
+
+ try {
+ await conexionBD.beginTransaction();
+
+ // Check for duplicate name only if name is being updated
+ if (datosRol.nombre !== null && datosRol.nombre !== undefined) {
+ const resultadoNombreDuplicado = await conexionBD.query(
+ 'SELECT idRol FROM rol WHERE nombre = ? AND idRol != ?',
+ [datosRol.nombre, idRol],
+ );
+
+ if (resultadoNombreDuplicado[0].length > 0) {
+ throw new Error(MENSAJES.ROL_EXISTENTE);
+ }
+ }
+
+ // Build dynamic UPDATE query based on which fields are provided
+ const camposActualizar = [];
+ const valoresActualizar = [];
+
+ if (datosRol.nombre !== null && datosRol.nombre !== undefined) {
+ camposActualizar.push('nombre = ?');
+ valoresActualizar.push(datosRol.nombre);
+ }
+
+ if (datosRol.descripcion !== null && datosRol.descripcion !== undefined) {
+ camposActualizar.push('descripcion = ?');
+ valoresActualizar.push(datosRol.descripcion);
+ }
+
+ // Only run UPDATE if there are fields to update
+ if (camposActualizar.length > 0) {
+ const consultaActualizar = `UPDATE rol
+ SET ${camposActualizar.join(', ')}
+ WHERE idRol = ?`;
+ valoresActualizar.push(idRol);
+
+ await conexionBD.query(consultaActualizar, valoresActualizar);
+ }
+
+ // Always handle permissions (delete old ones)
+ await conexionBD.query(
+ 'DELETE FROM rol_permiso WHERE idRol = ?',
+ [idRol],
+ );
+
+ // Insert new permissions if any
+ if (permisos.length > 0) {
+ const valores = permisos.map(idPermiso => [idRol, idPermiso]);
+ const marcadores = permisos.map(() => '(?, ?)').join(', ');
+ const consultaInsertar = `INSERT INTO rol_permiso (idRol, idPermiso)
+ VALUES ${marcadores}`;
+ const valoresAplanados = valores.flat();
+
+ await conexionBD.query(consultaInsertar, valoresAplanados);
+ }
+
+ await conexionBD.commit();
+
+ } catch (error) {
+ await conexionBD.rollback();
+ console.error('Error actualizando rol:', error);
+
+ if (error.message === MENSAJES.ROL_EXISTENTE
+ || error.message === MENSAJES.PARAMETROS_INVALIDOS.mensaje) {
+ throw new Error(error.message);
+ } else {
+ throw new Error('Ocurrio un error al actualizar rol.');
+ }
+ } finally {
+ conexionBD.release();
+ }
+};
\ No newline at end of file
diff --git a/Roles/Datos/Repositorios/repositorioCrearRol.js b/Roles/Datos/Repositorios/repositorioCrearRol.js
new file mode 100644
index 00000000..c2734053
--- /dev/null
+++ b/Roles/Datos/Repositorios/repositorioCrearRol.js
@@ -0,0 +1,72 @@
+const db = require('@altertex/util/bd/db');
+const QUERY = require('@altertex/util/const/consultasRoles');
+
+/**
+ * Verifica si un rol con el nombre especificado ya existe en la base de datos.
+ *
+ * @async
+ * @function verificarNombreRol
+ * @param {string} nombre - Nombre del rol a verificar.
+ * @returns {Promise} Retorna `true` si el rol existe, `false` en caso contrario.
+ */
+exports.verificarNombreRol = async (nombre) => {
+ const [rows] = await db.execute(QUERY.VERIFICAR_NOMBRE_ROL, [nombre]);
+ return rows.length > 0;
+};
+
+/**
+ * Verifica si un permiso con el ID especificado existe en la base de datos.
+ *
+ * @async
+ * @function verificarPermiso
+ * @param {number} idPermiso - ID del permiso a verificar.
+ * @returns {Promise} Retorna `true` si el permiso existe, `false` en caso contrario.
+ */
+exports.verificarPermiso = async (idPermiso) => {
+ const [rows] = await db.execute(QUERY.VERIFICAR_PERMISO, [idPermiso]);
+ return rows.length > 0;
+};
+
+/**
+ * Inserta un nuevo rol en la base de datos.
+ *
+ * @async
+ * @function crearRol
+ * @param {string} nombre - Nombre del nuevo rol.
+ * @param {string} descripcion - Descripción del nuevo rol.
+ * @returns {Promise} Retorna el resultado de la operación de inserción, incluyendo el ID del nuevo rol.
+ */
+exports.crearRol = async (nombre, descripcion) => {
+ const [resultado] = await db.execute(QUERY.INSERTAR_ROL, [nombre, descripcion]);
+ return resultado;
+};
+
+/**
+ * Asocia una lista de permisos a un rol específico en la base de datos.
+ * Realiza la operación en una transacción para asegurar la integridad de los datos.
+ *
+ * @async
+ * @function asociarPermisosARol
+ * @param {number} idRol - ID del rol al que se asociarán los permisos.
+ * @param {number[]} permisos - Lista de IDs de permisos a asociar.
+ * @throws {Error} Lanza un error si ocurre algún fallo en la transacción.
+ * @returns {Promise}
+ */
+exports.asociarPermisosARol = async (idRol, permisos) => {
+ const conexion = await db.getConnection();
+
+ try {
+ await conexion.beginTransaction();
+
+ for (const idPermiso of permisos) {
+ await conexion.execute(QUERY.INSERTAR_ROL_PERMISO, [idRol, idPermiso]);
+ }
+
+ await conexion.commit();
+ } catch {
+ await conexion.rollback();
+ throw new Error('Error asociando permisos al rol');
+ } finally {
+ conexion.release();
+ }
+};
\ No newline at end of file
diff --git a/Roles/Datos/Repositorios/repositorioDetalleRol.js b/Roles/Datos/Repositorios/repositorioDetalleRol.js
new file mode 100644
index 00000000..b950287a
--- /dev/null
+++ b/Roles/Datos/Repositorios/repositorioDetalleRol.js
@@ -0,0 +1,29 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_ROLES = require('@altertex/util/const/consultasRoles');
+/**
+ * RF8 - Leer detalle de un rol
+ * Documentación del requisito funcional:
+ * https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF8
+ *
+ * @async
+ * @function obtenerDetalleRol
+ * @param {number} idRol - ID del rol que se desea consultar.
+ * @returns {Promise>} Arreglo de objetos con datos del rol y sus permisos asociados.
+ *
+ * @throws {Error} Si ocurre un error en la consulta a la base de datos.
+ */
+exports.obtenerDetalleRol = async (idRol) => {
+ const query = CONSULTAS_ROLES.OBTENER_DETALLE_ROL;
+
+ try {
+ const resultado = await correrQuery(query, [idRol]);
+
+ if (!resultado || resultado.length === 0) {
+ throw new Error('Rol no encontrado');
+ }
+
+ return resultado;
+ } catch {
+ throw new Error('Error al consultar el detalle del rol');
+ }
+};
\ No newline at end of file
diff --git a/Roles/Datos/Repositorios/repositorioRoles.js b/Roles/Datos/Repositorios/repositorioRoles.js
new file mode 100644
index 00000000..c406dd2b
--- /dev/null
+++ b/Roles/Datos/Repositorios/repositorioRoles.js
@@ -0,0 +1,44 @@
+// Importa la función encargada de ejecutar consultas SQL hacia la base de datos.
+const correrQuery = require('@altertex/util/ser/correrQuery');
+
+// Importa el objeto que contiene las sentencias SQL relacionadas con la entidad de roles.
+const CONSULTAS_ROLES = require('@altertex/util/const/consultasRoles');
+
+/**
+ * RF7 - Consultar lista de roles
+ * Documentación del requisito funcional:
+ * https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF7
+ *
+ * @async
+ * @function obtenerRoles
+ * @returns {Promise>} Retorna una lista de objetos que representan los roles obtenidos desde la base de datos.
+ *
+ * @throws {Error} Si no se encuentran resultados o si ocurre un error al ejecutar la consulta.
+ *
+ * @description
+ * Esta función ejecuta la consulta SQL para obtener la lista de roles desde la base de datos.
+ * En caso de que no se encuentren registros, arroja un error indicando que no hay roles registrados.
+ * Si ocurre un error en la ejecución de la consulta, se lanza un error genérico para manejo por el controlador.
+ */
+exports.obtenerRoles = async () => {
+ // Consulta SQL para obtener la lista completa de roles.
+ const query = CONSULTAS_ROLES.OBTENER_LISTA;
+
+ try {
+ // Ejecuta la consulta SQL utilizando la función utilitaria.
+ const roles = await correrQuery(query);
+
+ // Verifica si la respuesta está vacía.
+ if (!roles || roles.length === 0) {
+ throw new Error('No hay roles registrados');
+ }
+
+ // Retorna los resultados si existen.
+ return roles;
+ } catch {
+ // Imprime en consola el error para fines de depuración.
+
+ // Lanza un nuevo error genérico para ser manejado por el controlador correspondiente.
+ throw new Error('Error al consultar roles');
+ }
+};
diff --git a/Roles/Datos/Repositorios/repositoriorEliminar.js b/Roles/Datos/Repositorios/repositoriorEliminar.js
new file mode 100644
index 00000000..9da5d8c2
--- /dev/null
+++ b/Roles/Datos/Repositorios/repositoriorEliminar.js
@@ -0,0 +1,49 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS = require('@altertex/util/const/consultasRoles');
+const MENSAJES = require('@altertex/util/const/mensajesRoles');
+
+// RF10 - Eliminar rol - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF10
+
+/**
+ * Elimina uno o varios roles de la base de datos según los IDs proporcionados.
+ *
+ * @async
+ * @function eliminarRol
+ * @param {number[]} ids - Un arreglo de identificadores de roles a eliminar.
+ * @returns {Promise} - No retorna ningún valor si la operación es exitosa.
+ * @throws {Error} - Lanza un error si ocurre un fallo en la consulta o si no se eliminó ningún rol.
+ */
+exports.eliminarRol = async (ids) => {
+ try {
+ if (!Array.isArray(ids) || ids.length === 0) return;
+
+ const placeholdersValidar = ids.map(() => '?').join(', ');
+ const queryValidar = CONSULTAS.VALIDAR_ROL_SIN_USUARIOS.replace('__IDS__', placeholdersValidar);
+ const resultadoValidacion = await correrQuery(queryValidar, ids);
+
+ if (resultadoValidacion[0].cantidad > 0) {
+ throw new Error(MENSAJES.ELIMINAR_ROL_ERROR.mensaje_rol_asignado);
+ }
+
+ const placeholders = ids.map(() => '?').join(', ');
+ const query = CONSULTAS.ELIMINAR_ROL.replace('__IDS__', placeholders);
+ const resultado = await correrQuery(query, ids);
+
+ if (resultado.affectedRows === 0) {
+ throw new Error(MENSAJES.ELIMINAR_ROL_ERROR.mensaje_no_existe);
+ }
+
+ return;
+ } catch (error) {
+ // Si el error es uno de los definidos (mensaje de MENSAJES), lo relanzamos tal cual
+ if (
+ error.message === MENSAJES.ELIMINAR_ROL_ERROR.mensaje_rol_asignado
+ || error.message === MENSAJES.ELIMINAR_ROL_ERROR.mensaje_no_existe
+ ) {
+ throw error;
+ }
+
+ // Si es un error técnico (como SQL), se reemplaza por el mensaje general
+ throw new Error(MENSAJES.ELIMINAR_ROL_ERROR.mensaje);
+ }
+};
diff --git a/Roles/Rutas/RutasIndividuales/actualizarRol.routes.js b/Roles/Rutas/RutasIndividuales/actualizarRol.routes.js
new file mode 100644
index 00000000..76fe2262
--- /dev/null
+++ b/Roles/Rutas/RutasIndividuales/actualizarRol.routes.js
@@ -0,0 +1,15 @@
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/rol/ctrl/actualizarRol.controller');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+const revisarPermisos = require('@altertex/util/inter/verificarPermisos');
+
+ruteador.put(RUTAS.ROLES.ACTUALIZAR, validarYSanitizar, revisarApiKey(), autorizarToken, limitePeticionesDiarias, revisarPermisos(PERMISOS.ACTUALIZAR_ROL), controlador.actualizarRol);
+
+module.exports = ruteador;
\ No newline at end of file
diff --git a/Roles/Rutas/RutasIndividuales/consultarDetalleRol.routes.js b/Roles/Rutas/RutasIndividuales/consultarDetalleRol.routes.js
new file mode 100644
index 00000000..027bbac2
--- /dev/null
+++ b/Roles/Rutas/RutasIndividuales/consultarDetalleRol.routes.js
@@ -0,0 +1,54 @@
+const express = require('express');
+const ruteador = express.Router();
+
+const controlador = require('@altertex/rol/ctrl/consultarDetalleRol.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * RF## - Leer detalle de un rol - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF##
+ */
+
+/**
+ * @swagger
+ * /api/roles/leer:
+ * get:
+ * summary: Obtener detalle de un rol
+ * description: Devuelve nombre, descripción, cantidad de usuarios y permisos de un rol específico.
+ * tags: [Roles]
+ * security:
+ * - ApiKeyAuth: []
+ * parameters:
+ * - in: query
+ * name: idRol
+ * required: true
+ * schema:
+ * type: integer
+ * description: ID del rol a consultar.
+ * responses:
+ * 200:
+ * description: Detalle del rol obtenido exitosamente.
+ * 400:
+ * description: Parámetros inválidos.
+ * 404:
+ * description: Rol no encontrado.
+ * 500:
+ * description: Error interno del servidor.
+ */
+ruteador.get(
+ RUTAS.ROLES.LEER_ROL,
+ validarYSanitizar,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.LEER_ROL),
+ controlador.consultarDetalle,
+);
+
+module.exports = ruteador;
\ No newline at end of file
diff --git a/Roles/Rutas/RutasIndividuales/consultarLista.routes.js b/Roles/Rutas/RutasIndividuales/consultarLista.routes.js
new file mode 100644
index 00000000..873bdf8d
--- /dev/null
+++ b/Roles/Rutas/RutasIndividuales/consultarLista.routes.js
@@ -0,0 +1,62 @@
+// Importación del framework Express para crear rutas HTTP.
+const express = require('express');
+
+// Se crea una instancia del enrutador de Express para definir rutas específicas del módulo de roles.
+const ruteador = express.Router();
+
+// Importación del controlador que contiene la lógica para manejar la consulta de lista de roles.
+const controlador = require('@altertex/rol/ctrl/consultarLista.controller');
+
+// Importación de middlewares de seguridad:
+// - revisarApiKey: valida la API Key.
+// - autorizarToken: valida el token JWT del usuario.
+// - verificarPermisos: verifica que el usuario tenga el permiso necesario para acceder al recurso.
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+
+// Importación de constantes que definen los permisos y las rutas de la aplicación.
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/roles/consultar-lista:
+ * post:
+ * summary: Consulta la lista de roles disponibles en el sistema.
+ * tags:
+ * - Roles
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * responses:
+ * 200:
+ * description: Consulta exitosa. Devuelve la lista de roles.
+ * 204:
+ * description: No se encontraron roles registrados.
+ * 401:
+ * description: Token inválido o expirado.
+ * 403:
+ * description: Permisos insuficientes para acceder a esta ruta.
+ * 500:
+ * description: Error interno del servidor.
+ */
+
+// Se define la ruta POST para consultar la lista de roles.
+// Esta ruta está protegida por tres middlewares:
+// 1. Validación de API Key.
+// 2. Validación del token JWT del usuario.
+// 3. Verificación de que el usuario tenga el permiso "CONSULTAR_ROLES".
+ruteador.post(
+ RUTAS.ROLES.CONSULTAR_LISTA,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CONSULTAR_ROLES),
+ controlador.consultarLista
+);
+
+// Exporta el enrutador configurado para que pueda ser usado por el enrutador principal de la aplicación.
+module.exports = ruteador;
diff --git a/Roles/Rutas/RutasIndividuales/crearRol.routes.js b/Roles/Rutas/RutasIndividuales/crearRol.routes.js
new file mode 100644
index 00000000..850d00a4
--- /dev/null
+++ b/Roles/Rutas/RutasIndividuales/crearRol.routes.js
@@ -0,0 +1,126 @@
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/rol/ctrl/crearRol.controller');
+
+const RUTAS = require('@altertex/util/const/rutas');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+/**
+ * @swagger
+ * /api/roles/crear-rol:
+ * post:
+ * summary: Crear un nuevo rol en el sistema
+ * description: Crea un nuevo rol con sus permisos asociados. Solo usuarios autorizados pueden crear roles.
+ * tags:
+ * - Roles
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * required:
+ * - nombre
+ * - descripcion
+ * - permisos
+ * properties:
+ * nombre:
+ * type: string
+ * description: Nombre del rol
+ * example: "Supervisor de Producción"
+ * descripcion:
+ * type: string
+ * description: Descripción detallada del rol
+ * example: "Supervisa las actividades de producción y gestiona el personal operativo"
+ * permisos:
+ * type: array
+ * description: Lista de IDs de permisos asignados al rol
+ * items:
+ * type: integer
+ * example: [1, 2, 3, 4]
+ * responses:
+ * 201:
+ * description: Rol creado exitosamente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Rol creado exitosamente"
+ * rol:
+ * type: object
+ * properties:
+ * id:
+ * type: integer
+ * example: 1
+ * nombre:
+ * type: string
+ * example: "Supervisor de Producción"
+ * descripcion:
+ * type: string
+ * example: "Supervisa las actividades de producción y gestiona el personal operativo"
+ * permisos:
+ * type: array
+ * items:
+ * type: integer
+ * example: [1, 2, 3, 4]
+ * 400:
+ * description: Error en los datos proporcionados
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Datos inválidos para crear el rol"
+ * 401:
+ * description: No autorizado
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "No autorizado"
+ * 403:
+ * description: Forbidden - No tiene permisos suficientes
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "No tiene permisos para crear roles"
+ * 500:
+ * description: Error interno del servidor
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Error al crear el rol"
+ */
+
+ruteador.post(
+ RUTAS.ROLES.CREAR_ROL,
+ validarYSanitizar,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ controlador.crearRol
+);
+
+module.exports = ruteador;
diff --git a/Roles/Rutas/RutasIndividuales/eliminarRol.routes.js b/Roles/Rutas/RutasIndividuales/eliminarRol.routes.js
new file mode 100644
index 00000000..4f830d63
--- /dev/null
+++ b/Roles/Rutas/RutasIndividuales/eliminarRol.routes.js
@@ -0,0 +1,78 @@
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/rol/ctrl/eliminarRol.controller');
+const PERMISOS = require('@altertex/util/const/permisos');
+
+const RUTAS = require('@altertex/util/const/rutas');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const revisarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+// RF10 - Eliminar rol - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF10
+
+/**
+ * @swagger
+ * /api/roles/eliminar:
+ * delete:
+ * tags:
+ * - Roles
+ * summary: Eliminar uno o varios roles
+ * description: |
+ * Elimina uno o varios roles del sistema según los IDs proporcionados.
+ * Requiere API Key, token JWT y permisos adecuados.
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * idsRol:
+ * type: array
+ * items:
+ * type: integer
+ * example: [1, 2, 3]
+ * required:
+ * - idsRol
+ * responses:
+ * 200:
+ * description: Rol(es) eliminado(s) correctamente
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Se elimino el rol correctamente
+ * 400:
+ * description: Error en la solicitud o el rol no existe
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Ocurrió un error al eliminar rol
+ * 401:
+ * description: No autorizado - Token JWT faltante o inválido
+ * 403:
+ * description: Prohibido - Permiso insuficiente
+ * 500:
+ * description: Error inesperado del servidor
+ */
+ruteador.post(
+ RUTAS.ROLES.ELIMINAR_ROL,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ revisarPermisos(PERMISOS.ELIMINAR_ROL),
+ controlador.eliminarRol
+);
+
+module.exports = ruteador;
diff --git a/Roles/Rutas/RutasIndividuales/obtenerOpcionesRol.routes.js b/Roles/Rutas/RutasIndividuales/obtenerOpcionesRol.routes.js
new file mode 100644
index 00000000..c3e8974c
--- /dev/null
+++ b/Roles/Rutas/RutasIndividuales/obtenerOpcionesRol.routes.js
@@ -0,0 +1,33 @@
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/rol/ctrl/obtenerOpcionesRol.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+
+/**
+ * @file obtenerOpcionesRol.routes.js
+ * @description Define la ruta para obtener las opciones de permisos disponibles al crear o editar un rol.
+ *
+ * Esta ruta aplica la verificación de API Key como medida de seguridad antes de ejecutar el controlador.
+ */
+
+/**
+ * POST /obtener-opciones
+ *
+ * Obtiene los permisos disponibles para ser asignados a un rol.
+ * - Protegida con middleware que verifica que se incluya una API Key válida.
+ *
+ * @route {POST} /api/roles/obtener-opciones
+ * @middleware revisarApiKey
+ * @controller obtenerOpcionesRol
+ */
+ruteador.post(
+ '/obtener-opciones',
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ controlador.obtenerOpcionesRol,
+);
+
+module.exports = ruteador;
diff --git a/Roles/Rutas/indexRoles.routes.js b/Roles/Rutas/indexRoles.routes.js
new file mode 100644
index 00000000..5f70fd94
--- /dev/null
+++ b/Roles/Rutas/indexRoles.routes.js
@@ -0,0 +1,52 @@
+/**
+ * @file indexRoles.routes.js
+ * @description
+ * Encargado de centralizar y registrar todas las rutas relacionadas con la entidad "Rol".
+ * Este archivo importa las rutas individuales (por funcionalidad) y las monta bajo un prefijo base común,
+ * facilitando así la organización modular de las rutas dentro del sistema.
+ */
+
+// Importación del framework Express para la gestión de rutas HTTP.
+const express = require('express');
+
+// Se crea una nueva instancia del enrutador de Express para agrupar rutas del módulo de roles.
+const ruteador = express.Router();
+
+// Importación del archivo que contiene las rutas individuales para consultar la lista de roles.
+const rutasConsultarLista = require('@altertex/rol/rutasInd/consultarLista.routes');
+
+const rutasCrearRol = require('@altertex/rol/rutasInd/crearRol.routes');
+
+const rutasObtenerOpcionesRol = require('@altertex/rol/rutasInd/obtenerOpcionesRol.routes');
+
+const rutasEliminarRol = require('@altertex/rol/rutasInd/eliminarRol.routes');
+
+const rutasConsultarDetalle = require('@altertex/rol/rutasInd/consultarDetalleRol.routes');
+
+const rutasActualizarRol = require('@altertex/rol/rutasInd/actualizarRol.routes');
+
+// Importación del archivo de constantes donde están definidas las rutas base del sistema.
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * Se monta el grupo de rutas relacionadas con roles bajo el prefijo definido.
+ * Por convención, este prefijo suele ser: /api/roles
+ *
+ * Ejemplo final de ruta expuesta:
+ * POST /api/roles/consultar-lista
+ */
+ruteador.use(RUTAS.ROLES.BASE, rutasConsultarLista);
+
+ruteador.use(RUTAS.ROLES.BASE, rutasCrearRol);
+
+ruteador.use(RUTAS.ROLES.BASE, rutasObtenerOpcionesRol);
+
+ruteador.use(RUTAS.ROLES.BASE, rutasEliminarRol);
+
+ruteador.use(RUTAS.ROLES.BASE, rutasConsultarDetalle);
+
+ruteador.use(RUTAS.ROLES.BASE, rutasActualizarRol);
+
+
+// Exporta el enrutador para ser utilizado en el archivo principal de rutas de la aplicación (por ejemplo: app.js).
+module.exports = ruteador;
\ No newline at end of file
diff --git a/SetsProductos/Controladores/actualizarSetsProductos.controller.js b/SetsProductos/Controladores/actualizarSetsProductos.controller.js
new file mode 100644
index 00000000..ae6d0fcf
--- /dev/null
+++ b/SetsProductos/Controladores/actualizarSetsProductos.controller.js
@@ -0,0 +1,53 @@
+const MENSAJES = require('@altertex/util/const/mensajesSetsProductos');
+const repositorio = require('@altertex/setspro/repos/repositorioActualizarSetsProductos');
+//RF[44] Actualizar set de productos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF44]
+
+/**
+ * Controlador HTTP para actualizar un set de productos.
+ *
+ * Valida que el cuerpo de la solicitud contenga los datos necesarios,
+ * y delega la lógica de actualización al repositorio correspondiente.
+ *
+ * Respuestas posibles:
+ * - 400 si faltan datos en el cuerpo de la solicitud.
+ * - 200 si el set se actualiza correctamente.
+ * - 500 si ocurre un error en el proceso de actualización.
+ *
+ * @async
+ * @function actualizarSetProductos
+ * @param {Express.Request} req - Objeto de solicitud HTTP de Express.
+ * @param {Express.Response} res - Objeto de respuesta HTTP de Express.
+ * @returns {Promise} La respuesta HTTP con el estado y mensaje correspondiente.
+ */
+exports.actualizarSetProductos = async (req, res) => {
+ const datosActualizacion = req.body;
+ const cliente = req.user.clienteSeleccionado;
+
+ // Validación básica de datos requeridos
+ if (
+ !datosActualizacion
+ || !datosActualizacion.nombre
+ || !datosActualizacion.productos
+ || !Array.isArray(datosActualizacion.productos)
+ ) {
+ return res.status(MENSAJES.FORMATO_INVALIDO_DATOS.codigo).json({
+ mensaje: MENSAJES.FORMATO_INVALIDO_DATOS.mensaje,
+ detalles: 'Se requieren nombre y lista de productos',
+ });
+ }
+
+ try {
+ await repositorio.actualizarSetProductos(cliente, datosActualizacion);
+
+ return res.status(MENSAJES.SET_ACTUALIZADO.codigo).json({
+ mensaje: MENSAJES.SET_ACTUALIZADO.mensaje,
+ datos: datosActualizacion,
+ });
+ } catch (error) {
+ console.error('Error al actualizar set de productos:', error);
+
+ return res.status(MENSAJES.ERROR_ACTUALIZAR_SET.codigo).json({
+ mensaje: error.message,
+ });
+ }
+};
diff --git a/SetsProductos/Controladores/consultarSetsProductos.controller.js b/SetsProductos/Controladores/consultarSetsProductos.controller.js
new file mode 100644
index 00000000..26c4b7d0
--- /dev/null
+++ b/SetsProductos/Controladores/consultarSetsProductos.controller.js
@@ -0,0 +1,52 @@
+const repositorio = require('@altertex/setspro/repos/repositorioConsultarSetsProductos');
+const MENSAJES_SETS_PRODUCTOS = require('@altertex/util/const/mensajesSetsProductos');
+
+/**
+ * Controlador para la consulta de la lista de sets de productos de un cliente.
+ *
+ * RF42 - Super Administrador, Cliente Consulta Lista de Sets de Productos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF42
+ *
+ * @async
+ * @function consultarLista
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.body - Cuerpo de la solicitud HTTP.
+ * @param {object} req.user - Datos del usuario autenticado.
+ * @param {number} req.user.clienteSeleccionado - ID del cliente seleccionado para la consulta.
+ * @param {object} res - Objeto de respuesta de Express.
+ *
+ * @returns {Response} Respuesta HTTP con estado:
+ * - 200 si la consulta es exitosa, junto con los datos de los sets de productos.
+ * - 204 y mensaje si no hay usuarios en la base de datos.
+ * - 500 si ocurre un error en el servidor.
+ *
+ * @throws {Error} Si ocurre un error inesperado durante la operación.
+ */
+exports.consultarLista = async (req, res) => {
+ const idCliente = parseInt(req.user.clienteSeleccionado);
+
+ // Validación del ID de cliente
+ if (!idCliente) {
+ return res
+ .status(MENSAJES_SETS_PRODUCTOS.PARAMETROS_INVALIDOS.codigo)
+ .json({ mensaje: MENSAJES_SETS_PRODUCTOS.PARAMETROS_INVALIDOS.mensaje });
+ }
+
+ try {
+ const resultados = await repositorio.obtenerSetsProductos(idCliente);
+
+ if (!resultados || resultados.length === 0) {
+ return res
+ .status(MENSAJES_SETS_PRODUCTOS.SIN_RESULTADOS.codigo)
+ .json({ mensaje: MENSAJES_SETS_PRODUCTOS.SIN_RESULTADOS.mensaje });
+ }
+
+ return res.status(MENSAJES_SETS_PRODUCTOS.CONSULTA_EXITOSA.codigo).json({
+ mensaje: MENSAJES_SETS_PRODUCTOS.CONSULTA_EXITOSA.mensaje,
+ setsProductos: resultados,
+ });
+ } catch {
+ return res
+ .status(MENSAJES_SETS_PRODUCTOS.ERROR_CONSULTAR_SETS_PRODUCTOS.codigo)
+ .json({ mensaje: MENSAJES_SETS_PRODUCTOS.ERROR_CONSULTAR_SETS_PRODUCTOS.mensaje });
+ }
+};
diff --git a/SetsProductos/Controladores/crearSetsProductos.controller.js b/SetsProductos/Controladores/crearSetsProductos.controller.js
new file mode 100644
index 00000000..96fc79a7
--- /dev/null
+++ b/SetsProductos/Controladores/crearSetsProductos.controller.js
@@ -0,0 +1,49 @@
+const MENSAJES_SETS_PRODUCTOS = require('@altertex/util/const/mensajesSetsProductos');
+const repositorio = require('@altertex/setspro/repos/repositorioCrearSetsProductos');
+
+/**
+ * Controlador de Express que maneja la creación de un nuevo set de productos para un cliente.
+ *
+ * Valida:
+ * - Que se haya enviado el cuerpo de la solicitud con los datos requeridos.
+ * - Que se hayan proporcionado todos los campos necesarios.
+ * - Que exista un cliente seleccionado en el usuario autenticado.
+ *
+ * Llama al repositorio para realizar la lógica de negocio y persistencia, y responde
+ * con el estado adecuado dependiendo del resultado.
+ *
+ * @async
+ * @function crearSetsProductos
+ * @param {Express.Request} req - Objeto de solicitud de Express.
+ * @param {Express.Response} res - Objeto de respuesta de Express.
+ *
+ * @returns {Promise} Devuelve una respuesta HTTP con el estado correspondiente.
+ *
+ * @throws {500} En caso de error inesperado en la creación del set.
+ */
+exports.crearSetsProductos = async (req, res) => {
+ const datos = req.body.nuevoSetsProductos;
+ const cliente = req.user.clienteSeleccionado;
+
+ if (!req.body.nuevoSetsProductos) {
+ return res.status(MENSAJES_SETS_PRODUCTOS.DATOS_INVALIDOS_ERROR.codigo).json({ mensaje: MENSAJES_SETS_PRODUCTOS.DATOS_INVALIDOS_ERROR.mensaje });
+ }
+
+
+ if (!datos.nombre || !datos.nombreVisible || !datos.descripcion || !datos.activo || !datos.idProductos) {
+ return res.status(MENSAJES_SETS_PRODUCTOS.DATOS_INVALIDOS_ERROR.codigo).json({ mensaje: MENSAJES_SETS_PRODUCTOS.DATOS_INVALIDOS_ERROR.mensaje });
+ }
+
+ if (!cliente) {
+ return res.status(MENSAJES_SETS_PRODUCTOS.CLIENTE_NO_SELECCIONADO.codigo).json({ mensaje: MENSAJES_SETS_PRODUCTOS.CLIENTE_NO_SELECCIONADO.mensaje });
+ }
+
+ try {
+ await repositorio.crearSetsProductos(cliente, datos);
+ return res.status(MENSAJES_SETS_PRODUCTOS.SETS_PRODUCTOS_CREADO_EXITO.codigo).json({ mensaje: MENSAJES_SETS_PRODUCTOS.SETS_PRODUCTOS_CREADO_EXITO.mensaje });
+ } catch (error) {
+ return res.status(500).json({ mensaje: error.message });
+ }
+
+
+};
\ No newline at end of file
diff --git a/SetsProductos/Controladores/eliminarSetsProductos.controller.js b/SetsProductos/Controladores/eliminarSetsProductos.controller.js
new file mode 100644
index 00000000..92316f69
--- /dev/null
+++ b/SetsProductos/Controladores/eliminarSetsProductos.controller.js
@@ -0,0 +1,48 @@
+const repositorio = require('@altertex/setspro/repos/repositorioEliminarSetsProductos');
+const MENSAJES_SETS_PRODUCTOS = require('@altertex/util/const/mensajesSetsProductos');
+
+/**
+ * Controlador para eliminar uno o más set de productos.
+ * //RF[45] Elimina set de productos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF45]
+ *
+ * @async
+ * @function eliminarSetProductos
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.body - Cuerpo de la solicitud HTTP.
+ * @param {number[]} req.body.idsSetProductos - Array de IDs numéricos de los sets de productos a eliminar.
+ * @param {object} res - Objeto de respuesta de Express.
+ * @returns {Promise} Respuesta HTTP con estado:
+ * - 200 si los sets de productos fueron eliminadas correctamente.
+ * - 404 si no se encontraron los sets de productos.
+ * - 500 si ocurre un error en el servidor.
+ * @throws {Error} Si ocurre un error durante la eliminación.
+ */
+exports.eliminarSetProductos = async (req, res) => {
+ try {
+ const idsSetsProductos = req.body.idsSetProductos;
+
+ if (!Array.isArray(idsSetsProductos) || idsSetsProductos.length === 0) {
+ return res.status(MENSAJES_SETS_PRODUCTOS.SET_PRODUCTO_NO_ENCONTRADO.codigo).json({
+ mensaje: MENSAJES_SETS_PRODUCTOS.SET_PRODUCTO_NO_ENCONTRADO.mensaje,
+ });
+ }
+
+ await Promise.all(
+ idsSetsProductos.map(async (idSetProducto) => {
+ const resultadoSetProducto = await repositorio.eliminarSetProducto(idSetProducto);
+
+ if (resultadoSetProducto.affectedRows === 0) {
+ throw new Error(`Set de productos con ID ${idSetProducto} no encontrado`);
+ }
+ })
+ );
+
+ return res.status(MENSAJES_SETS_PRODUCTOS.SET_PRODUCTOS_ELIMINADO.codigo).json({
+ mensaje: MENSAJES_SETS_PRODUCTOS.SET_PRODUCTOS_ELIMINADO.mensaje,
+ });
+ } catch {
+ return res.status(MENSAJES_SETS_PRODUCTOS.ERROR_ELIMINAR_SET_PRODUCTOS.codigo).json({
+ mensaje: MENSAJES_SETS_PRODUCTOS.ERROR_ELIMINAR_SET_PRODUCTOS.mensaje,
+ });
+ }
+};
diff --git a/SetsProductos/Datos/Repositorios/repositorioActualizarSetsProductos.js b/SetsProductos/Datos/Repositorios/repositorioActualizarSetsProductos.js
new file mode 100644
index 00000000..0e91e086
--- /dev/null
+++ b/SetsProductos/Datos/Repositorios/repositorioActualizarSetsProductos.js
@@ -0,0 +1,75 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const MENSAJES = require('@altertex/util/const/mensajesSetsProductos');
+const CONSULTAS = require('@altertex/util/const/consultasSetsProductos');
+
+// RF[44] Actualizar set de productos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF44]
+
+// RF[44] Actualizar set de productos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF44]
+
+/**
+ * Actualiza un set de productos con su información general y productos asociados.
+ *
+ * - Verifica que el nuevo nombre no esté duplicado para el cliente.
+ * - Actualiza los campos básicos del set: nombre, descripción y estado activo.
+ * - Si se especifica un arreglo de productos:
+ * - Elimina las asociaciones que ya no existen.
+ * - Agrega las nuevas asociaciones.
+ * - Si el arreglo está vacío, elimina todas las asociaciones.
+ *
+ * @async
+ * @function actualizarSetProductos
+ * @param {number} idCliente - ID del cliente propietario del set.
+ * @param {object} datos - Objeto con los datos para actualizar el set.
+ * @param {number} datos.idSetProducto - ID del set de productos a actualizar.
+ * @param {string} datos.nombre - Nombre interno del set.
+ * @param {string} datos.descripcion - Descripción del set.
+ * @param {boolean} datos.activo - Estado activo o inactivo del set.
+ * @param {number[]} datos.productos - Lista de IDs de productos asociados al set.
+ * Si es un arreglo vacío, se eliminarán todas las asociaciones.
+ * @throws {Error} Si ocurre un error durante la actualización o si el nombre está duplicado.
+ */
+exports.actualizarSetProductos = async (idCliente, datos) => {
+ const { idSetProducto, nombre, descripcion, activo, productos } = datos;
+
+ try {
+
+ const duplicados = await correrQuery(CONSULTAS.CONSULTAR_NOMBRE_DUPLICADO, [
+ idCliente,
+ idSetProducto,
+ nombre,
+ ]);
+
+ if (duplicados.length > 0) {
+ throw new Error(MENSAJES.ERROR_NOMBRE_NORMAL_DUPLICADO.mensaje);
+ }
+ // 1. Actualizar info básica del set
+ await correrQuery(CONSULTAS.ACTUALIZAR_SET_INFO, [nombre, descripcion, activo, idSetProducto]);
+
+ // 2. Manejar productos asociados al set
+ if (Array.isArray(productos)) {
+ if (productos.length > 0) {
+ // Verificar que los productos pertenezcan al cliente
+ const productosSTR = productos.join(', ');
+ const valores = productos
+ .map((idProducto) => `(${idSetProducto}, ${idProducto})`)
+ .join(', ');
+
+ // Eliminar asociaciones actuales que no estén en la nueva lista
+ await correrQuery(
+ CONSULTAS.ELIMINAR_PRODUCTOS_DEL_SET.replace('__ID__', idSetProducto).replace(
+ '__PRODUCTOS__',
+ productosSTR
+ )
+ );
+
+ // Agregar nuevos productos al set
+ await correrQuery(CONSULTAS.AGREGAR_PRODUCTOS_AL_SET.replace('__VALORES__', valores));
+ } else {
+ // Eliminar todas las asociaciones si el array está vacío
+ await correrQuery(CONSULTAS.ELIMINAR_TODOS_PRODUCTOS_DEL_SET, [idSetProducto]);
+ }
+ }
+ } catch (error) {
+ throw new Error(error.message || MENSAJES.ERROR_ACTUALIZAR_SET_PRODUCTOS.mensaje);
+ }
+};
diff --git a/SetsProductos/Datos/Repositorios/repositorioConsultarSetsProductos.js b/SetsProductos/Datos/Repositorios/repositorioConsultarSetsProductos.js
new file mode 100644
index 00000000..fabff938
--- /dev/null
+++ b/SetsProductos/Datos/Repositorios/repositorioConsultarSetsProductos.js
@@ -0,0 +1,28 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_SETS_PRODUCTOS = require('@altertex/util/const/consultasSetsProductos');
+
+/**
+ * Función para obtener los sets de productos de un cliente específico.
+ *
+ * RF42 - Super Administrador, Cliente Consulta Lista de Sets de Productos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF42
+ *
+ * @async
+ * @function obtenerSetsProductos
+ * @param {number} idCliente - ID del cliente cuyos sets de productos se desea obtener.
+ *
+ * @returns {Promise} Lista de sets de productos del cliente.
+ * - Si no se encuentran sets, se retorna un array vacío.
+ *
+ * @throws {Error} Si ocurre un error al ejecutar la consulta o si no se encuentran resultados.
+ */
+exports.obtenerSetsProductos = async (idCliente) => {
+ const query = CONSULTAS_SETS_PRODUCTOS.OBTENER_LISTA;
+
+ try {
+ const setsProductos = await correrQuery(query, [idCliente]);
+
+ return setsProductos;
+ } catch {
+ return [];
+ }
+};
diff --git a/SetsProductos/Datos/Repositorios/repositorioCrearSetsProductos.js b/SetsProductos/Datos/Repositorios/repositorioCrearSetsProductos.js
new file mode 100644
index 00000000..21623f34
--- /dev/null
+++ b/SetsProductos/Datos/Repositorios/repositorioCrearSetsProductos.js
@@ -0,0 +1,61 @@
+const MENSAJES_SETS_PRODUCTOS = require('@altertex/util/const/mensajesSetsProductos');
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS = require('@altertex/util/const/consultasSetsProductos');
+
+/**
+ * Crea un nuevo set de productos para un cliente específico, validando que:
+ * - El nombre y nombre visible del set no estén duplicados.
+ * - Todos los productos asociados existan.
+ *
+ * Si todo es válido, crea el set de productos y asigna los productos especificados al set.
+ *
+ * @async
+ * @function crearSetsProductos
+ * @param {number} idCliente - ID del cliente al que se le asignará el set de productos.
+ * @param {object} datosSetsProducto - Datos del set de productos a crear.
+ * @param {string} datosSetsProducto.nombre - Nombre interno del set.
+ * @param {string} datosSetsProducto.nombreVisible - Nombre visible del set.
+ * @param {string} [datosSetsProducto.descripcion] - Descripción del set (opcional).
+ * @param {boolean} datosSetsProducto.activo - Indicador de si el set estará activo.
+ * @param {number[]} datosSetsProducto.idProductos - IDs de los productos que se asociarán al set.
+ *
+ * @throws {Error} Si el nombre o nombre visible del set ya están en uso.
+ * @throws {Error} Si uno o más productos no existen en la base de datos.
+ * @throws {Error} Si ocurre un error inesperado durante la ejecución.
+ *
+ * @returns {Promise} No retorna un valor directamente, pero lanza errores si algo falla.
+ */
+exports.crearSetsProductos = async (idCliente, datosSetsProducto) => {
+ try {
+
+ const duplicados = await correrQuery(CONSULTAS.CONSULTAR_DUPLICADOS, [
+ idCliente,
+ datosSetsProducto.nombre,
+ datosSetsProducto.nombreVisible,
+ ]);
+
+ if (duplicados.length > 0) {
+ throw new Error(MENSAJES_SETS_PRODUCTOS.ERROR_NOMBRE_DUPLICADO.mensaje);
+ }
+
+ const ids = datosSetsProducto.idProductos;
+ const temporal = ids.map(() => '?').join(', ');
+ const queryProductos = CONSULTAS.CONSULTAR_PRODUCTOS_EXISTENTES.replace('__IDS__', temporal);
+ const productosExistentes = await correrQuery(queryProductos, ids);
+
+ if (productosExistentes.length !== ids.length) {
+ throw new Error(MENSAJES_SETS_PRODUCTOS.ERROR_PRODUCTOS_INVALIDOS.mensaje);
+ }
+
+ const resultado = await correrQuery(CONSULTAS.CREAR_SET_PRODUCTO, [idCliente, datosSetsProducto.nombre, datosSetsProducto.nombreVisible, datosSetsProducto.descripcion, datosSetsProducto.activo]);
+ const idSetProducto = resultado.insertId;
+
+
+ for (const producto of datosSetsProducto.idProductos) {
+ await correrQuery(CONSULTAS.ASIGNAR_PRODUCTO_SET_PRODUCTO, [producto, idSetProducto]);
+ }
+ } catch (error) {
+ throw new Error(error.message);
+ }
+
+};
\ No newline at end of file
diff --git a/SetsProductos/Datos/Repositorios/repositorioEliminarSetsProductos.js b/SetsProductos/Datos/Repositorios/repositorioEliminarSetsProductos.js
new file mode 100644
index 00000000..589d6cb8
--- /dev/null
+++ b/SetsProductos/Datos/Repositorios/repositorioEliminarSetsProductos.js
@@ -0,0 +1,53 @@
+const db = require('@altertex/util/bd/db');
+const CONSULTAS_SETS_PRODUCTOS = require('@altertex/util/const/consultasSetsProductos');
+
+/**
+ * Elimina un set de productos de la base de datos.
+ *
+ * @async
+ * @function eliminarSetProducto
+ * @param {number} idSetProducto - ID del set de productos a eliminar.
+ * @returns {Promise} Objeto de resultado de la operación MySQL (por ejemplo, `affectedRows`).
+ * @throws {Error} Si ocurre un error durante la ejecución del query para eliminar el set de productos.
+ */
+exports.eliminarSetProducto = async (idSetProducto) => {
+ const conexion = await db.getConnection();
+
+ try {
+ await conexion.beginTransaction();
+
+ const [resultadoSetGrupo] = await conexion.query(
+ CONSULTAS_SETS_PRODUCTOS.ELIMINAR_SET_PRODUCTOS_GRUPO_EMPLEADOS,
+ [idSetProducto]
+ );
+
+ const [resultadoProductosSetProductos] = await conexion.query(
+ CONSULTAS_SETS_PRODUCTOS.ELIMINAR_PRODUCTOS_SET_PRODUCTOS,
+ [idSetProducto]
+ );
+
+ const [resultadoSetProductos] = await conexion.query(
+ CONSULTAS_SETS_PRODUCTOS.ELIMINAR_SET_PRODUCTOS,
+ [idSetProducto]
+ );
+
+ if (resultadoSetProductos.affectedRows === 0) {
+ throw new Error(`Set de productos con ID ${idSetProducto} no encontrado`);
+ }
+
+ // Confirmar la transacción
+ await conexion.commit();
+
+ return {
+ mensaje: 'Set de productos eliminado correctamente',
+ resultadoSetGrupo,
+ resultadoProductosSetProductos,
+ resultadoSetProductos,
+ };
+ } catch {
+ await conexion.rollback();
+ throw new Error('Error eliminando set de productos');
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
\ No newline at end of file
diff --git a/SetsProductos/Rutas/RutasIndividuales/actualizarSetsProductos.routes.js b/SetsProductos/Rutas/RutasIndividuales/actualizarSetsProductos.routes.js
new file mode 100644
index 00000000..d2f5892b
--- /dev/null
+++ b/SetsProductos/Rutas/RutasIndividuales/actualizarSetsProductos.routes.js
@@ -0,0 +1,29 @@
+const express = require('express');
+const ruteador = express.Router();
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+const controlador = require('@altertex/setspro/ctrl/actualizarSetsProductos.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const revisarPermisos = require('@altertex/util/inter/verificarPermisos');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+//RF[19] Actualizar Empleado - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF19]
+
+/**
+ * @swagger...
+ */
+
+ruteador.put(
+ RUTAS.SETS_PRODUCTOS.ACTUALIZAR,
+ revisarApiKey(),
+ validarYSanitizar,
+ autorizarToken,
+ limitePeticionesDiarias,
+ revisarPermisos(PERMISOS.ACTUALIZAR_SET_PRODUCTOS),
+ controlador.actualizarSetProductos
+);
+
+module.exports = ruteador;
diff --git a/SetsProductos/Rutas/RutasIndividuales/consultarSetsProductos.routes.js b/SetsProductos/Rutas/RutasIndividuales/consultarSetsProductos.routes.js
new file mode 100644
index 00000000..2e7299fb
--- /dev/null
+++ b/SetsProductos/Rutas/RutasIndividuales/consultarSetsProductos.routes.js
@@ -0,0 +1,69 @@
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/setspro/ctrl/consultarSetsProductos.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * RF42 - Super Administrador, Cliente Consulta Lista de Sets de Productos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF42
+ */
+
+/**
+ * @swagger
+ * /api/sets-productos/consultar-lista:
+ * post:
+ * summary: Consulta la lista de sets de productos disponibles.
+ * description: Permite a un Super Administrador o Cliente consultar la lista de sets de productos registrados.
+ * tags:
+ * - Sets de Productos
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * responses:
+ * 200:
+ * description: Lista de sets de productos obtenida exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * setsProductos:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * idSetProducto:
+ * type: string
+ * description: ID único del set de producto.
+ * nombre:
+ * type: string
+ * description: Nombre del set de producto.
+ * descripcion:
+ * type: string
+ * description: Descripción del set de producto.
+ * activo:
+ * type: integer
+ * description: Indica si el set de producto está activo (1) o inactivo (0).
+ * 401:
+ * description: No autorizado. El token es inválido o ha expirado.
+ * 403:
+ * description: No tiene permisos para consultar la lista de sets de productos.
+ * 500:
+ * description: Error interno del servidor.
+ */
+
+ruteador.post(
+ RUTAS.SETS_PRODUCTOS.CONSULTAR_LISTA,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CONSULTAR_SETS_PRODUCTOS),
+ controlador.consultarLista
+);
+
+module.exports = ruteador;
diff --git a/SetsProductos/Rutas/RutasIndividuales/crearSetsProductos.routes.js b/SetsProductos/Rutas/RutasIndividuales/crearSetsProductos.routes.js
new file mode 100644
index 00000000..22a05c6b
--- /dev/null
+++ b/SetsProductos/Rutas/RutasIndividuales/crearSetsProductos.routes.js
@@ -0,0 +1,89 @@
+const express = require('express');
+const ruteador = express.Router();
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+
+const controlador = require('@altertex/setspro/ctrl/crearSetsProductos.controller');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/sets-productos/crear:
+ * post:
+ * summary: Crea un nuevo set de productos para un cliente autenticado.
+ * tags:
+ * - Sets de Productos
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * nuevoSetsProductos:
+ * type: object
+ * required:
+ * - nombre
+ * - nombreVisible
+ * - descripcion
+ * - activo
+ * - idProductos
+ * properties:
+ * nombre:
+ * type: string
+ * example: "combo-verano"
+ * nombreVisible:
+ * type: string
+ * example: "Combo de Verano"
+ * descripcion:
+ * type: string
+ * example: "Incluye productos para la temporada de verano"
+ * activo:
+ * type: boolean
+ * example: true
+ * idProductos:
+ * type: array
+ * items:
+ * type: integer
+ * example: [1, 2, 3]
+ * responses:
+ * 201:
+ * description: Set de productos creado exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Set de productos creado correctamente."
+ * 400:
+ * description: Datos inválidos o faltantes en la solicitud.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Los datos enviados son inválidos."
+ * 401:
+ * description: Token de autenticación no válido o ausente.
+ * 403:
+ * description: Permisos insuficientes para crear sets de productos.
+ * 429:
+ * description: Límite diario de peticiones alcanzado.
+ * 500:
+ * description: Error interno del servidor al crear el set de productos.
+ */
+ruteador.post(RUTAS.SETS_PRODUCTOS.CREAR, validarYSanitizar, revisarApiKey(), autorizarToken, limitePeticionesDiarias, verificarPermisos(PERMISOS.CREAR_SET_PRODUCTOS), controlador.crearSetsProductos);
+
+module.exports = ruteador;
\ No newline at end of file
diff --git a/SetsProductos/Rutas/RutasIndividuales/eliminarSetsProductos.routes.js b/SetsProductos/Rutas/RutasIndividuales/eliminarSetsProductos.routes.js
new file mode 100644
index 00000000..d3e9b14f
--- /dev/null
+++ b/SetsProductos/Rutas/RutasIndividuales/eliminarSetsProductos.routes.js
@@ -0,0 +1,77 @@
+//RF[45] Elimina set de productos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF45]
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/setspro/ctrl/eliminarSetsProductos.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/sets-productos/eliminar:
+ * delete:
+ * summary: Eliminar sets de productos.
+ * description: Elimina uno o varios sets de productos de la base de datos. Requiere autenticación y permisos específicos.
+ * tags:
+ * - Sets de Productos
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * idsSet:
+ * type: array
+ * items:
+ * type: integer
+ * example: [101, 102, 103]
+ * responses:
+ * 200:
+ * description: Sets eliminados exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Sets eliminados correctamente.
+ * 404:
+ * description: Sets no encontrados.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: No se encontraron los sets especificados.
+ * 500:
+ * description: Error interno al eliminar los sets.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * example: Error al eliminar los sets.
+ */
+
+ruteador.post(
+ RUTAS.SETS_PRODUCTOS.ELIMINAR_SET_PRODUCTOS,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.ELIMINAR_SET_PRODUCTOS),
+ controlador.eliminarSetProductos
+);
+
+module.exports = ruteador;
diff --git a/SetsProductos/Rutas/indexSetsProductos.routes.js b/SetsProductos/Rutas/indexSetsProductos.routes.js
new file mode 100644
index 00000000..b1f8e1c2
--- /dev/null
+++ b/SetsProductos/Rutas/indexSetsProductos.routes.js
@@ -0,0 +1,21 @@
+const express = require('express');
+const ruteador = express.Router();
+const rutasConsultarSetsProductos = require('@altertex/setspro/rutasInd/consultarSetsProductos.routes');
+const rutasEliminarSetsProductos = require('@altertex/setspro/rutasInd/eliminarSetsProductos.routes');
+const rutasCrearSetsProductos = require('@altertex/setspro/rutasInd/crearSetsProductos.routes');
+const rutasActualizarSetsProductos = require('@altertex/setspro/rutasInd/actualizarSetsProductos.routes');
+
+const RUTAS = require('@altertex/util/const/rutas');
+
+//RF42 - Super Administrador, Cliente Consulta Lista de Sets de Productos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF42
+ruteador.use(RUTAS.SETS_PRODUCTOS.BASE, rutasConsultarSetsProductos);
+
+//RF[45] Elimina set de productos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF45]
+ruteador.use(RUTAS.SETS_PRODUCTOS.BASE, rutasEliminarSetsProductos);
+
+ruteador.use(RUTAS.SETS_PRODUCTOS.BASE, rutasCrearSetsProductos);
+
+//RF[44] Actualizar set de productos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF44]
+ruteador.use(RUTAS.SETS_PRODUCTOS.BASE, rutasActualizarSetsProductos);
+
+module.exports = ruteador;
diff --git a/Usuarios/Controladores/consultarListaUsuarios.controller.js b/Usuarios/Controladores/consultarListaUsuarios.controller.js
new file mode 100644
index 00000000..1a52225f
--- /dev/null
+++ b/Usuarios/Controladores/consultarListaUsuarios.controller.js
@@ -0,0 +1,38 @@
+const repositorio = require('@altertex/usu/repos/repositorioConsultarListaUsuarios');
+const MENSAJES_USUARIOS = require('@altertex/util/const/mensajesUsuarios');
+
+/**
+ * Controlador que maneja la consulta de la lista de usuarios.
+ * RF02 - Super Administrador Consulta Lista de Usuarios -
+ * https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF2
+ *
+ * @function consultarListaUsuarios
+ * @async
+ * @param {object} req - Objeto de solicitud HTTP (Request).
+ * @param {object} res - Objeto de respuesta HTTP (Response).
+ *
+ * @returns {Response} Retorna una respuesta con:
+ * - Código 200 y lista de usuarios si se encuentran resultados.
+ * - Código 200 y mensaje si no hay usuarios en la base de datos.
+ * - Código 500 y mensaje de error si ocurre una falla en la consulta.
+ */
+exports.consultarListaUsuarios = async (req, res) => {
+ try {
+ const resultados = await repositorio.consultarListaUsuarios();
+
+ if (!resultados || resultados.length === 0) {
+ return res
+ .status(MENSAJES_USUARIOS.USUARIOS_NO_ENCONTRADOS.codigo)
+ .json({ mensaje: MENSAJES_USUARIOS.USUARIOS_NO_ENCONTRADOS.mensaje });
+ }
+
+ return res.status(MENSAJES_USUARIOS.LISTA_USUARIOS_OBTENIDA.codigo).json({
+ mensaje: MENSAJES_USUARIOS.LISTA_USUARIOS_OBTENIDA.mensaje,
+ listaUsuarios: resultados,
+ });
+ } catch {
+ return res
+ .status(MENSAJES_USUARIOS.ERROR_OBTENER_USUARIOS.codigo)
+ .json({ mensaje: MENSAJES_USUARIOS.ERROR_OBTENER_USUARIOS.mensaje });
+ }
+};
diff --git a/Usuarios/Controladores/crearUsuario.controller.js b/Usuarios/Controladores/crearUsuario.controller.js
new file mode 100644
index 00000000..ddac86e4
--- /dev/null
+++ b/Usuarios/Controladores/crearUsuario.controller.js
@@ -0,0 +1,120 @@
+const repositorio = require('@altertex/usu/repos/repositorioCrearUsuario');
+const bcrypt = require('bcryptjs');
+const MENSAJES_USUARIOS = require('@altertex/util/const/mensajesUsuarios');
+
+/**
+ * Controlador para crear un nuevo usuario.
+ * RF1 - Crear Usuario - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF1
+ * @async
+ * @function crearUsuario
+ * @param {object} req - Objeto de solicitud de Express.
+ * @param {object} req.body - Cuerpo de la solicitud HTTP.
+ * @param {string} req.body.nombreCompleto - Nombre completo del usuario.
+ * @param {string} req.body.correoElectronico - Correo electrónico del usuario.
+ * @param {string} req.body.contrasenia - Contraseña proporcionada por el usuario (sin hashear).
+ * @param {string} req.body.numeroTelefono - Número de teléfono del usuario.
+ * @param {string} req.body.direccion - Dirección del usuario.
+ * @param {string} req.body.fechaNacimiento - Fecha de nacimiento en formato YYYY-MM-DD.
+ * @param {string} req.body.genero - Género del usuario.
+ * @param {boolean} req.body.estatus - Estatus activo/inactivo del usuario.
+ * @param {object} res - Objeto de respuesta de Express.
+ *
+ * @returns {Response} Respuesta HTTP con estado:
+ * - 201 si el usuario se creó correctamente.
+ * - 400 si faltan campos requeridos.
+ * - 401 si no se pudo crear el usuario.
+ * - 500 si ocurre un error en el servidor.
+ *
+ * @throws {Error}
+ *
+ */
+exports.crearUsuario = async (req, res) => {
+ const {
+ nombreCompleto,
+ correoElectronico,
+ contrasenia,
+ numeroTelefono,
+ direccion,
+ fechaNacimiento,
+ genero,
+ estatus,
+ idRol,
+ idCliente,
+ } = req.body;
+
+ if (
+ !nombreCompleto
+ || !correoElectronico
+ || !contrasenia
+ || !numeroTelefono
+ || !direccion
+ || !fechaNacimiento
+ || !genero
+ || estatus === undefined
+ || !idRol
+ || idCliente === undefined
+ || (Array.isArray(idCliente) && idCliente.length === 0)
+ ) {
+ return res.status(400).json({ mensaje: 'Faltan campos requeridos' });
+ }
+
+ const correoValido = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ if (!correoValido.test(correoElectronico)) {
+ return res
+ .status(MENSAJES_USUARIOS.CORREO_INVALIDO.codigo)
+ .json({ mensaje: MENSAJES_USUARIOS.CORREO_INVALIDO.mensaje });
+ }
+
+ const tieneCaracterEspecial = /[!@#$%^&*(),.?":{}|<>]/;
+ const tieneMayuscula = /[A-Z]/;
+ if (contrasenia.length < 8) {
+ return res
+ .status(MENSAJES_USUARIOS.CONTRASENA_DEBIL.codigo)
+ .json({ mensaje: MENSAJES_USUARIOS.CONTRASENA_DEBIL.mensaje });
+ }
+
+ if (!tieneCaracterEspecial.test(contrasenia)) {
+ return res
+ .status(MENSAJES_USUARIOS.CONTRASENA_DEBIL.codigo)
+ .json({ mensaje: MENSAJES_USUARIOS.CONTRASENA_DEBIL.mensaje });
+ }
+
+ if (!tieneMayuscula.test(contrasenia)) {
+ return res.status(MENSAJES_USUARIOS.CONTRASENA_DEBIL.codigo).json({
+ mensaje: 'La contraseña debe contener al menos una letra mayúscula.',
+ });
+ }
+
+ const telefonoValido = /^\d{10}$/;
+ if (!telefonoValido.test(numeroTelefono)) {
+ return res
+ .status(MENSAJES_USUARIOS.TELEFONO_INVALIDO.codigo)
+ .json({ mensaje: MENSAJES_USUARIOS.TELEFONO_INVALIDO.mensaje });
+ }
+
+ try {
+ const contraseniaEncriptada = await bcrypt.hash(contrasenia, 10);
+
+ const resultado = await repositorio.crearUsuarioConAsociaciones(
+ nombreCompleto,
+ correoElectronico,
+ contraseniaEncriptada,
+ numeroTelefono,
+ direccion,
+ fechaNacimiento,
+ genero,
+ estatus,
+ idRol,
+ idCliente
+ );
+
+ return res.status(MENSAJES_USUARIOS.USUARIO_CREADO.codigo).json({
+ mensaje: MENSAJES_USUARIOS.USUARIO_CREADO.mensaje,
+ idUsuario: resultado.idUsuario,
+ });
+ } catch {
+ return res
+ .status(MENSAJES_USUARIOS.ERROR_CREAR_USUARIO.codigo)
+ .json({ mensaje: MENSAJES_USUARIOS.ERROR_CREAR_USUARIO.mensaje });
+ }
+};
diff --git a/Usuarios/Controladores/eliminarUsuario.controller.js b/Usuarios/Controladores/eliminarUsuario.controller.js
new file mode 100644
index 00000000..7078f34a
--- /dev/null
+++ b/Usuarios/Controladores/eliminarUsuario.controller.js
@@ -0,0 +1,94 @@
+const repositorio = require('@altertex/usu/repos/repositorioEliminarUsuario');
+const MENSAJES_USUARIOS = require('@altertex/util/const/mensajesUsuarios');
+const db = require('@altertex/util/bd/db');
+const { verificarCodigo2FA } = require('@altertex/util/ser/verificarCodigo2FA.servicio');
+const repoUsuariosProtegidos = require('@altertex/usu/repos/repositorioConsultarUsuariosProtegidos');
+
+/**
+ * Controlador para eliminar uno o varios usuarios, con validación adicional si hay Superadmins involucrados.
+ *
+ * RF5 - Eliminar Usuario
+ * Documentación: https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/rf5/
+ *
+ * @async
+ * @function eliminarUsuario
+ * @param {object} req - Objeto de solicitud HTTP.
+ * @param {object} res - Objeto de respuesta HTTP.
+ * @returns {Promise} Retorna una respuesta JSON con el resultado de la operación.
+ *
+ * @description
+ * Este controlador:
+ * 1. Recibe IDs de usuarios a eliminar.
+ * 2. Valida si hay Superadmins entre ellos.
+ * 3. Si los hay, valida que el usuario solicitante tenga permiso y pase la verificación 2FA.
+ * 4. Luego delega la eliminación al repositorio.
+ */
+exports.eliminarUsuario = async (req, res) => {
+ try {
+
+ let idsUsuarios = req.body.ids;
+ const codigo2FA = req.body.codigo2FA;
+ const idSolicitante = req.user?.idUsuario;
+
+ // Validación: Se requiere al menos un ID
+ if (!idsUsuarios || (Array.isArray(idsUsuarios) && idsUsuarios.length === 0)) {
+ return res.status(MENSAJES_USUARIOS.PARAMETROS_INVALIDOS.codigo).json({
+ mensaje: MENSAJES_USUARIOS.PARAMETROS_INVALIDOS.mensaje,
+ });
+ }
+
+ if (!Array.isArray(idsUsuarios)) {
+ idsUsuarios = [idsUsuarios];
+ }
+
+ const idsNumericos = idsUsuarios.map(Number);
+
+ const [usuariosObjetivo] = await db.query(`
+ SELECT u.idUsuario, r.nombre AS rol
+ FROM usuario u
+ JOIN usuario_rol ur ON u.idUsuario = ur.idUsuario
+ JOIN rol r ON ur.idRol = r.idRol
+ WHERE u.idUsuario IN (?)
+ `, [idsNumericos]);
+
+ const contieneSuperadmins = usuariosObjetivo.some(usuar => usuar.rol === 'Super Administrador');
+
+ if (contieneSuperadmins) {
+ const [resultadoPermiso] = await db.query(
+ 'SELECT puedeEliminarSuperadmins FROM usuarios_2fa WHERE idUsuario = ? AND tiene2FA = true',
+ [idSolicitante]
+ );
+
+ const tienePermiso = resultadoPermiso?.[0]?.puedeEliminarSuperadmins;
+
+ if (!tienePermiso) {
+ return res.status(403).json({
+ mensaje: 'No tienes permiso para eliminar Superadmins.',
+ });
+ }
+
+ const esCodigoValido = await verificarCodigo2FA(idSolicitante, codigo2FA);
+ if (!esCodigoValido) {
+ return res.status(401).json({
+ mensaje: 'Código 2FA inválido o expirado.',
+ });
+ }
+ }
+
+ const usuariosProtegidos = await repoUsuariosProtegidos.consultarUsuariosProtegidos(idsNumericos);
+
+ if (usuariosProtegidos.length > 0) {
+ return res.status(403).json({
+ mensaje: 'No puedes eliminar Super administradores protegidos del sistema.',
+ });
+ }
+
+ await repositorio.eliminarUsuarios(idsNumericos);
+
+ return res.status(200).json({ mensaje: 'Usuarios eliminados correctamente' });
+ } catch {
+ return res.status(MENSAJES_USUARIOS.ERROR_ELIMINAR_USUARIO.codigo).json({
+ mensaje: MENSAJES_USUARIOS.ERROR_ELIMINAR_USUARIO.mensaje,
+ });
+ }
+};
\ No newline at end of file
diff --git a/Usuarios/Controladores/leerUsuario.controller.js b/Usuarios/Controladores/leerUsuario.controller.js
new file mode 100644
index 00000000..2fd2b690
--- /dev/null
+++ b/Usuarios/Controladores/leerUsuario.controller.js
@@ -0,0 +1,43 @@
+const repositorio = require('@altertex/usu/repos/repositorioLeerUsuario');
+const MENSAJES_USUARIOS = require('@altertex/util/const/mensajesUsuarios');
+
+/**
+ * Lee los detalles de un usuario desde la base de datos utilizando su ID.
+ *
+ * Valida el parámetro `idUsuario` y obtiene la información del usuario a través del repositorio.
+ * Si el usuario no es encontrado o el parámetro es inválido, retorna un error.
+ *
+ * @param {Express.Request} req - La solicitud HTTP que contiene el `idUsuario` en el cuerpo.
+ * @param {Express.Response} res - La respuesta HTTP para enviar el resultado al cliente.
+ * @returns {Promise} Responde con el usuario encontrado o un mensaje de error.
+ *
+ * @see [RF03 Leer usuario](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF3)
+ */
+exports.leerUsuario = async (req, res) => {
+ const idUsuario = parseInt(req.body.idUsuario);
+
+ if (isNaN(idUsuario)) {
+ return res
+ .status(MENSAJES_USUARIOS.PARAMETROS_INVALIDOS.codigo)
+ .json({ mensaje: MENSAJES_USUARIOS.PARAMETROS_INVALIDOS.mensaje });
+ }
+
+ try {
+ const usuario = await repositorio.obtenerUsuarioPorId(idUsuario);
+
+ if (!usuario) {
+ return res
+ .status(MENSAJES_USUARIOS.USUARIO_NO_ENCONTRADO.codigo)
+ .json({ mensaje: MENSAJES_USUARIOS.USUARIO_NO_ENCONTRADO.mensaje });
+ }
+
+ return res.status(MENSAJES_USUARIOS.USUARIO_OBTENIDO.codigo).json({
+ mensaje: MENSAJES_USUARIOS.USUARIO_OBTENIDO.mensaje,
+ usuario,
+ });
+ } catch {
+ return res
+ .status(MENSAJES_USUARIOS.ERROR_OBTENER_USUARIO.codigo)
+ .json({ mensaje: MENSAJES_USUARIOS.ERROR_OBTENER_USUARIO.mensaje });
+ }
+};
\ No newline at end of file
diff --git a/Usuarios/Datos/Repositorios/repositorioConsultarListaUsuarios.js b/Usuarios/Datos/Repositorios/repositorioConsultarListaUsuarios.js
new file mode 100644
index 00000000..af6c8dca
--- /dev/null
+++ b/Usuarios/Datos/Repositorios/repositorioConsultarListaUsuarios.js
@@ -0,0 +1,30 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_USUARIOS = require('@altertex/util/const/consultasUsuarios');
+
+/**
+ * Consulta la lista de usuarios en la base de datos.
+ * RF02 - Super Administrador Consulta Lista de Usuarios -
+ * https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF2
+ *
+ * @async
+ * @function consultarListaUsuarios
+ *
+ * @returns {Promise} Arreglo de objetos con los datos de los usuarios.
+ * Cada objeto puede incluir propiedades como `id`, `nombre`, `correo`, `rol`, etc.
+ *
+ * @throws {Error} Si ocurre un error durante la ejecución del query a la base de datos.
+ *
+ * @description
+ * Ejecuta una consulta SQL definida en `CONSULTAS_USUARIOS.OBTENER_LISTA` utilizando el
+ * servicio `correrQuery`. Se utiliza para obtener la lista completa de usuarios registrados.
+ */
+exports.consultarListaUsuarios = async () => {
+ const query = CONSULTAS_USUARIOS.OBTENER_LISTA;
+
+ try {
+ const listaUsuarios = await correrQuery(query);
+ return listaUsuarios;
+ } catch {
+ throw new Error('Error consultando la lista de usuarios');
+ }
+};
diff --git a/Usuarios/Datos/Repositorios/repositorioConsultarUsuariosProtegidos.js b/Usuarios/Datos/Repositorios/repositorioConsultarUsuariosProtegidos.js
new file mode 100644
index 00000000..7ba32d7d
--- /dev/null
+++ b/Usuarios/Datos/Repositorios/repositorioConsultarUsuariosProtegidos.js
@@ -0,0 +1,20 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_USUARIOS = require('@altertex/util/const/consultasUsuarios');
+
+/**
+ * Consulta si existen usuarios protegidos dentro de una lista de IDs.
+ * @param {number[]} idsUsuarios - Lista de IDs a verificar
+ * @returns {Promise} Lista de usuarios protegidos encontrados
+ */
+exports.consultarUsuariosProtegidos = async (idsUsuarios) => {
+ try {
+ const resultado = await correrQuery(
+ CONSULTAS_USUARIOS.CONSULTAR_USUARIOS_PROTEGIDOS,
+ [idsUsuarios]
+ );
+ return resultado;
+ } catch (error) {
+ console.error('Error en consultarUsuariosProtegidos:', error);
+ throw new Error('Error consultando usuarios protegidos');
+ }
+};
\ No newline at end of file
diff --git a/Usuarios/Datos/Repositorios/repositorioCrearUsuario.js b/Usuarios/Datos/Repositorios/repositorioCrearUsuario.js
new file mode 100644
index 00000000..6abbf94d
--- /dev/null
+++ b/Usuarios/Datos/Repositorios/repositorioCrearUsuario.js
@@ -0,0 +1,70 @@
+const db = require('@altertex/util/bd/db');
+const CONSULTAS_USUARIOS = require('@altertex/util/const/consultasUsuarios');
+
+/**
+ * Crea un usuario y lo asocia a un rol y a uno o varios clientes en una transacción.
+ *
+ * @param {string} nombreCompleto
+ * @param {string} correoElectronico
+ * @param {string} contrasenia
+ * @param {string} numeroTelefono
+ * @param {string} direccion
+ * @param {string} fechaNacimiento
+ * @param {string} genero
+ * @param {boolean} estatus
+ * @param {number} idRol
+ * @param {number[]|number} idCliente
+ * @returns {Promise} Resultado con idUsuario
+ */
+exports.crearUsuarioConAsociaciones = async (
+ nombreCompleto,
+ correoElectronico,
+ contrasenia,
+ numeroTelefono,
+ direccion,
+ fechaNacimiento,
+ genero,
+ estatus,
+ idRol,
+ idCliente
+) => {
+ const conexion = await db.getConnection();
+
+ try {
+ await conexion.beginTransaction();
+
+ const valoresUsuario = [
+ nombreCompleto,
+ correoElectronico,
+ contrasenia,
+ numeroTelefono,
+ direccion,
+ fechaNacimiento,
+ genero,
+ estatus
+ ];
+
+ // 1. Insertar usuario
+ const [resultadoUsuario] = await conexion.query(CONSULTAS_USUARIOS.CREAR_USUARIO, valoresUsuario);
+ const idUsuario = resultadoUsuario.insertId;
+
+ // 2. Asociar rol
+ await conexion.query(CONSULTAS_USUARIOS.ASIGNAR_ROL_A_USUARIO, [idUsuario, idRol]);
+
+ // 3. Asociar a clientes
+ const clientes = Array.isArray(idCliente) ? idCliente : [idCliente];
+
+ for (const clienteId of clientes) {
+ await conexion.query(CONSULTAS_USUARIOS.ASOCIAR_USUARIO_A_CLIENTE, [idUsuario, clienteId]);
+ }
+
+ await conexion.commit();
+ return { success: true, idUsuario };
+
+ } catch (error) {
+ if (conexion) await conexion.rollback();
+ throw error;
+ } finally {
+ if (conexion) conexion.release();
+ }
+};
\ No newline at end of file
diff --git a/Usuarios/Datos/Repositorios/repositorioEliminarUsuario.js b/Usuarios/Datos/Repositorios/repositorioEliminarUsuario.js
new file mode 100644
index 00000000..c3b223e2
--- /dev/null
+++ b/Usuarios/Datos/Repositorios/repositorioEliminarUsuario.js
@@ -0,0 +1,68 @@
+// RF5 - Eliminar Usuario - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/rf5/
+
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_USUARIOS = require('@altertex/util/const/consultasUsuarios');
+
+/**
+ * Elimina uno o varios usuarios de la base de datos junto con todas sus relaciones.
+ * @param {Array} usuarios - IDs de los usuarios a eliminar
+ * @returns {Promise} - `true` si la eliminación fue exitosa, `false` si no se encontraron usuarios.
+ */
+exports.eliminarUsuarios = async (usuarios) => {
+ try {
+ // 1. Obtener los IDs de empleados asociados a estos usuarios
+ const empleados = await correrQuery(CONSULTAS_USUARIOS.OBTENER_EMPLEADOS_POR_USUARIOS, [
+ usuarios,
+ ]);
+
+ if (empleados && empleados.length > 0) {
+ const idsEmpleados = empleados.map((empleado) => empleado.idEmpleado);
+
+ // 2. Eliminar todas las relaciones de empleado en orden
+
+ // 2.1 Eliminar cuota_set_grupo_empleado
+ await correrQuery(CONSULTAS_USUARIOS.ELIMINAR_CUOTA_SET_GRUPO_EMPLEADO, [idsEmpleados]);
+
+ // 2.2 Eliminar empleado_evento
+ await correrQuery(CONSULTAS_USUARIOS.ELIMINAR_EMPLEADO_EVENTO, [idsEmpleados]);
+
+ // 2.3 Eliminar empleado_grupo
+ await correrQuery(CONSULTAS_USUARIOS.ELIMINAR_EMPLEADO_GRUPO, [idsEmpleados]);
+
+ // 2.4 Eliminar empleado_pedido
+ await correrQuery(CONSULTAS_USUARIOS.ELIMINAR_EMPLEADO_PEDIDO, [idsEmpleados]);
+
+ // 2.5 Eliminar tipo_pago_empleado
+ await correrQuery(CONSULTAS_USUARIOS.ELIMINAR_TIPO_PAGO_EMPLEADO, [idsEmpleados]);
+ }
+
+ // 3. Obtener los IDs de carritos asociados a estos usuarios
+ const carritos = await correrQuery(CONSULTAS_USUARIOS.OBTENER_CARRITOS_POR_USUARIOS, [
+ usuarios,
+ ]);
+
+ if (carritos && carritos.length > 0) {
+ const idsCarritos = carritos.map((carrito) => carrito.idCarrito);
+
+ // 3.1 Eliminar registros relacionados en carrito_opcion
+ await correrQuery(CONSULTAS_USUARIOS.ELIMINAR_CARRITO_OPCION, [idsCarritos]);
+
+ // 3.2 Eliminar registros del carrito
+ await correrQuery(CONSULTAS_USUARIOS.ELIMINAR_CARRITO_POR_USUARIOS, [usuarios]);
+ }
+
+ // 4. Eliminar registros de usuario_rol y usuario_cliente
+ await correrQuery(CONSULTAS_USUARIOS.ELIMINAR_USUARIO_ROL, [usuarios]);
+ await correrQuery(CONSULTAS_USUARIOS.ELIMINAR_USUARIO_CLIENTE, [usuarios]);
+
+ // 5. Ahora sí podemos eliminar los empleados
+ await correrQuery(CONSULTAS_USUARIOS.ELIMINAR_EMPLEADO_POR_USUARIOS, [usuarios]);
+
+ // 6. Finalmente, eliminar los usuarios
+ const resultado = await correrQuery(CONSULTAS_USUARIOS.ELIMINAR_USUARIOS_POR_IDS, [usuarios]);
+
+ return resultado.affectedRows > 0;
+ } catch {
+ throw new Error('No se pudieron eliminar los usuarios. Consulta el log para más detalles.');
+ }
+};
diff --git a/Usuarios/Datos/Repositorios/repositorioLeerUsuario.js b/Usuarios/Datos/Repositorios/repositorioLeerUsuario.js
new file mode 100644
index 00000000..c32a2a92
--- /dev/null
+++ b/Usuarios/Datos/Repositorios/repositorioLeerUsuario.js
@@ -0,0 +1,38 @@
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const CONSULTAS_USUARIOS = require('@altertex/util/const/consultasUsuarios');
+
+/**
+ * Obtiene un usuario desde la base de datos mediante su ID.
+ *
+ * Ejecuta una consulta SQL y retorna el primer usuario encontrado o `null` si no existe.
+ *
+ * @param {number|string} idUsuario - ID del usuario a buscar.
+ * @returns {Promise} El usuario encontrado o `null` si no existe.
+ * @throws {Error} Si ocurre un error al ejecutar la consulta.
+ *
+ * @see [RF03 Leer usuario](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF3)
+ */
+exports.obtenerUsuarioPorId = async (idUsuario) => {
+ const query = CONSULTAS_USUARIOS.LEER_USUARIO;
+ const resultado = await correrQuery(query, [idUsuario]);
+
+ if (resultado.length === 0) return null;
+
+ const usuario = {
+ idUsuario: resultado[0].idUsuario,
+ nombreCompleto: resultado[0].nombreCompleto,
+ correoElectronico: resultado[0].correoElectronico,
+ numeroTelefono: resultado[0].numeroTelefono,
+ direccion: resultado[0].direccion,
+ fechaNacimiento: resultado[0].fechaNacimiento,
+ genero: resultado[0].genero,
+ estatus: resultado[0].estatus,
+ rol: resultado[0].rol,
+ clientes: resultado.map((row) => ({
+ idCliente: row.idCliente,
+ nombreCliente: row.nombreCliente,
+ })),
+ };
+
+ return usuario;
+};
\ No newline at end of file
diff --git a/Usuarios/Rutas/RutasIndividuales/consultarListaUsuarios.routes.js b/Usuarios/Rutas/RutasIndividuales/consultarListaUsuarios.routes.js
new file mode 100644
index 00000000..6f2f575f
--- /dev/null
+++ b/Usuarios/Rutas/RutasIndividuales/consultarListaUsuarios.routes.js
@@ -0,0 +1,97 @@
+//RF02 Super Administrador Consulta Lista de Usuarios - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF2
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/usu/ctrl/consultarListaUsuarios.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/usuarios/consultar-lista-usuarios:
+ * post:
+ * summary: Consulta la lista de usuarios del sistema.
+ * tags: [Usuarios]
+ * security:
+ * - ApiKeyAuth: []
+ * responses:
+ * 200:
+ * description: Lista de usuarios obtenida exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Lista de usuarios obtenida exitosamente"
+ * usuarios:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * idUsuario:
+ * type: integer
+ * example: 123
+ * nombre:
+ * type: string
+ * example: "Juan Pérez"
+ * correo:
+ * type: string
+ * example: "juan.perez@example.com"
+ * telefono:
+ * type: string
+ * example: "5551234567"
+ * rol:
+ * type: string
+ * example: "Administrador"
+ * estatus:
+ * type: integer
+ * example: 1
+ * 401:
+ * description: No autorizado - Token inválido o faltante.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "No autorizado"
+ * 403:
+ * description: Prohibido - No tiene permisos para realizar esta acción.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "No tiene permisos para consultar la lista de usuarios"
+ * 500:
+ * description: Error interno del servidor.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Error al obtener la lista de usuarios"
+ */
+
+ruteador.post(
+ RUTAS.USUARIOS.CONSULTAR_LISTA_USUARIOS,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CONSULTAR_USUARIOS),
+ controlador.consultarListaUsuarios
+);
+
+module.exports = ruteador;
diff --git a/Usuarios/Rutas/RutasIndividuales/crearUsuario.routes.js b/Usuarios/Rutas/RutasIndividuales/crearUsuario.routes.js
new file mode 100644
index 00000000..132ef0d0
--- /dev/null
+++ b/Usuarios/Rutas/RutasIndividuales/crearUsuario.routes.js
@@ -0,0 +1,123 @@
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/usu/ctrl/crearUsuario.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+/**
+ * RF1 - Crear Usuario - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF1
+ */
+
+/**
+ * @swagger
+ * /api/usuarios/crear:
+ * post:
+ * summary: Crea un nuevo usuario en el sistema.
+ * tags:
+ * - Usuarios
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * required:
+ * - nombreCompleto
+ * - correoElectronico
+ * - contrasenia
+ * - numeroTelefono
+ * - direccion
+ * - fechaNacimiento
+ * - genero
+ * - estatus
+ * - idRol
+ * - idCliente
+ * properties:
+ * nombreCompleto:
+ * type: string
+ * example: Juan Pérez
+ * correoElectronico:
+ * type: string
+ * format: email
+ * example: juan.perez@example.com
+ * contrasenia:
+ * type: string
+ * example: Segura$123
+ * numeroTelefono:
+ * type: string
+ * example: "5551234567"
+ * direccion:
+ * type: string
+ * example: Av. Central 123, CDMX
+ * fechaNacimiento:
+ * type: string
+ * format: date
+ * example: 1990-05-20
+ * genero:
+ * type: string
+ * enum: [Hombre, Mujer, Otro]
+ * estatus:
+ * type: integer
+ * example: 1
+ * idRol:
+ * type: integer
+ * example: 2
+ * idCliente:
+ * type: integer
+ * example: 101
+ * responses:
+ * 201:
+ * description: Usuario creado exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Usuario creado correctamente.
+ * 400:
+ * description: Error de validación o entrada sospechosa.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Entrada sospechosa en el campo "correoElectronico".
+ * 401:
+ * description: No autorizado.
+ * 403:
+ * description: Permisos insuficientes.
+ * 500:
+ * description: Error interno del servidor.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Error al crear usuario.
+ */
+
+ruteador.post(
+ RUTAS.USUARIOS.CREAR,
+ validarYSanitizar,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.CREAR_USUARIO),
+ controlador.crearUsuario
+);
+
+module.exports = ruteador;
diff --git a/Usuarios/Rutas/RutasIndividuales/eliminarUsuario.routes.js b/Usuarios/Rutas/RutasIndividuales/eliminarUsuario.routes.js
new file mode 100644
index 00000000..bb37ec27
--- /dev/null
+++ b/Usuarios/Rutas/RutasIndividuales/eliminarUsuario.routes.js
@@ -0,0 +1,84 @@
+// RF5 - Eliminar Usuario - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/rf5/
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/usu/ctrl/eliminarUsuario.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+/**
+ * @swagger
+ * /api/usuarios/eliminar-usuarios:
+ * delete:
+ * summary: Eliminar usuarios
+ * description: Elimina uno o varios usuarios de la base de datos. Requiere autenticación y permisos específicos.
+ * tags:
+ * - Usuarios
+ * security:
+ * - ApiKeyAuth: []
+ * - BearerAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * ids:
+ * oneOf:
+ * - type: integer
+ * example: 93
+ * - type: array
+ * items:
+ * type: integer
+ * example: [1, 2, 3]
+ * responses:
+ * 200:
+ * description: Usuarios eliminados correctamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: Usuarios eliminados correctamente.
+ * 404:
+ * description: Usuarios no encontrados.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example:
+ * mensaje: No se encontraron los usuarios especificados.
+ * 500:
+ * description: Error interno al eliminar los usuarios.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example:
+ * mensaje: Error al eliminar los usuarios.
+ */
+
+ruteador.post(
+ RUTAS.USUARIOS.ELIMINAR_USUARIOS,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.ELIMINAR_USUARIOS),
+ controlador.eliminarUsuario
+);
+
+module.exports = ruteador;
diff --git a/Usuarios/Rutas/RutasIndividuales/leerUsuario.routes.js b/Usuarios/Rutas/RutasIndividuales/leerUsuario.routes.js
new file mode 100644
index 00000000..4485e114
--- /dev/null
+++ b/Usuarios/Rutas/RutasIndividuales/leerUsuario.routes.js
@@ -0,0 +1,122 @@
+/**
+ * RF[03] Leer usuario - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF3
+ */
+
+/**
+ * @swagger
+ * /api/usuarios/consultar-usuario:
+ * post:
+ * summary: Consulta la información de un usuario específico.
+ * tags: [Usuarios]
+ * security:
+ * - ApiKeyAuth: []
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * idUsuario:
+ * type: integer
+ * example: 123
+ * required:
+ * - idUsuario
+ * responses:
+ * 200:
+ * description: Usuario encontrado exitosamente.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Información del usuario obtenida exitosamente."
+ * usuario:
+ * type: object
+ * properties:
+ * idUsuario:
+ * type: integer
+ * example: 123
+ * nombre:
+ * type: string
+ * example: "Juan Pérez"
+ * correo:
+ * type: string
+ * example: "juan.perez@example.com"
+ * telefono:
+ * type: string
+ * example: "5551234567"
+ * direccion:
+ * type: string
+ * example: "Calle Ejemplo 123"
+ * fechaNacimiento:
+ * type: string
+ * format: date
+ * example: "1990-01-01"
+ * genero:
+ * type: string
+ * example: "Masculino"
+ * rol:
+ * type: string
+ * example: "Administrador"
+ * clientes:
+ * type: array
+ * items:
+ * type: object
+ * properties:
+ * idCliente:
+ * type: integer
+ * example: 123
+ * nombreCliente:
+ * type: string
+ * example: "Cliente ABC"
+ * estatus:
+ * type: integer
+ * example: 1
+ * 404:
+ * description: Usuario no encontrado.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "No se encontró un usuario con el ID proporcionado."
+ * 400:
+ * description: Error interno del servidor al consultar el usuario.
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * mensaje:
+ * type: string
+ * example: "Ocurrió un error al obtener los datos del usuario."
+ */
+
+const express = require('express');
+const ruteador = express.Router();
+const controlador = require('@altertex/usu/ctrl/leerUsuario.controller');
+const revisarApiKey = require('@altertex/util/inter/revisarApiKey');
+const autorizarToken = require('@altertex/util/inter/autorizarToken');
+const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar');
+const verificarPermisos = require('@altertex/util/inter/verificarPermisos');
+const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones');
+
+const PERMISOS = require('@altertex/util/const/permisos');
+const RUTAS = require('@altertex/util/const/rutas');
+
+ruteador.post(
+ RUTAS.USUARIOS.LEER,
+ validarYSanitizar,
+ revisarApiKey(),
+ autorizarToken,
+ limitePeticionesDiarias,
+ verificarPermisos(PERMISOS.LEER_USUARIO),
+ controlador.leerUsuario
+);
+
+module.exports = ruteador;
\ No newline at end of file
diff --git a/Usuarios/Rutas/indexUsuarios.routes.js b/Usuarios/Rutas/indexUsuarios.routes.js
new file mode 100644
index 00000000..5dc5ed19
--- /dev/null
+++ b/Usuarios/Rutas/indexUsuarios.routes.js
@@ -0,0 +1,15 @@
+const express = require('express');
+const ruteador = express.Router();
+const rutasCrearUsuario = require('@altertex/usu/rutasInd/crearUsuario.routes');
+const rutasLeerUsuario = require('@altertex/usu/rutasInd/leerUsuario.routes');
+const rutasConsultarListaUsuarios = require('@altertex/usu/rutasInd/consultarListaUsuarios.routes');
+const rutasEliminarUsuario = require('@altertex/usu/rutasInd/eliminarUsuario.routes');
+
+const RUTAS = require('@altertex/util/const/rutas');
+
+ruteador.use(RUTAS.USUARIOS.BASE, rutasConsultarListaUsuarios);
+ruteador.use(RUTAS.USUARIOS.BASE, rutasCrearUsuario);
+ruteador.use(RUTAS.USUARIOS.BASE, rutasLeerUsuario);
+ruteador.use(RUTAS.USUARIOS.BASE, rutasEliminarUsuario);
+
+module.exports = ruteador;
diff --git a/Utilidades/BaseDeDatos/db.js b/Utilidades/BaseDeDatos/db.js
new file mode 100644
index 00000000..1ce0b300
--- /dev/null
+++ b/Utilidades/BaseDeDatos/db.js
@@ -0,0 +1,53 @@
+const mysql = require('mysql2/promise');
+
+/**
+ * Establece un pool de conexiones con una base de datos MySQL utilizando las credenciales definidas
+ * en las variables de entorno. Incluye verificación inicial de conexión y soporte para UTF-8 multibyte.
+ *
+ * @module conexionMySQL
+ * @requires mysql2/promise
+ *
+ * @constant {object} pool - Pool de conexiones MySQL.
+ * @property {Function} query - Método para realizar consultas a la base de datos.
+ */
+
+const pool = mysql.createPool({
+ host: process.env.DB_HOST,
+ port: process.env.DB_PORT || 3306,
+ user: process.env.DB_USER,
+ password: process.env.DB_PASSWORD,
+ database: process.env.DB_NAME, // elimina espacios accidentales
+ charset: 'utf8mb4',
+ waitForConnections: true,
+ connectionLimit: 10,
+ queueLimit: 0,
+ enableKeepAlive: true,
+ keepAliveInitialDelay: 0, // Iniciar keepAlive inmediatamente
+ // Aumentar timeouts para mayor estabilidad
+ connectTimeout: 60000, // 60 segundos para conectar
+});
+
+// Verificar conexión inicial una vez al arrancar
+(async () => {
+ try {
+ const connection = await pool.getConnection();
+ console.log(`Conectado a MySQL con id ${connection.threadId}`);
+ connection.release(); // libera la conexión al pool
+ } catch (error) {
+ console.error('Error conectandose a MySQL:', error.stack);
+ }
+})();
+
+// Configurar un ping periódico para mantener las conexiones vivas
+const pingInterval = 30000; // 30 segundos
+setInterval(async () => {
+ try {
+ const connection = await pool.getConnection();
+ await connection.query('SELECT 1');
+ connection.release();
+ } catch (error) {
+ console.error('Error en ping a MySQL:', error.message);
+ }
+}, pingInterval);
+
+module.exports = pool;
\ No newline at end of file
diff --git a/Utilidades/Constantes/consultasCategorias.js b/Utilidades/Constantes/consultasCategorias.js
new file mode 100644
index 00000000..9d9f34c9
--- /dev/null
+++ b/Utilidades/Constantes/consultasCategorias.js
@@ -0,0 +1,77 @@
+module.exports = {
+ OBTENER_CATEGORIAS_CON_PRODUCTOS: `
+ SELECT
+ c.idCategoria,
+ c.nombreCategoria,
+ c.descripcion,
+ COUNT(p.idProducto) AS cantidadProductos
+ FROM
+ categoria c
+ LEFT JOIN categoria_producto cp ON c.idCategoria = cp.idCategoria
+ LEFT JOIN producto p ON cp.idProducto = p.idProducto AND p.idCliente = ?
+ GROUP BY
+ c.idCategoria, c.nombreCategoria, c.descripcion;
+ `,
+
+ CREAR_CATEGORIAS: `
+ INSERT INTO categoria (nombreCategoria, descripcion)
+ VALUES (?, ?);
+ `,
+
+ CREAR_CATEGORIA_PRODUCTOS: `
+ INSERT INTO categoria_producto (idCategoria, idProducto)
+ VALUES (?, ?);
+ `,
+
+ ELIMINAR_CATEGORIA_PRODUCTO: `
+ DELETE
+ FROM categoria_producto
+ WHERE idCategoria = ?;
+ `,
+
+ ELIMINAR_CATEGORIA: `
+ DELETE
+ FROM categoria
+ WHERE idCategoria = ?;
+ `,
+
+ CATEGORIA_EXISTENTE_POR_NOMBRE: `
+ SELECT idCategoria
+ FROM categoria
+ WHERE nombreCategoria = ?;
+ `,
+
+ PRODUCTOS_EXISTENTES_POR_IDS: `
+ SELECT idProducto
+ FROM producto
+ WHERE idProducto IN (?);
+ `,
+
+ LEER_DETALLE_CATEGORIA: `
+ SELECT
+ c.idCategoria,
+ c.nombreCategoria,
+ c.descripcion,
+ p.idProducto,
+ p.nombreComun
+ FROM categoria c
+ LEFT JOIN categoria_producto cp ON c.idCategoria = cp.idCategoria
+ LEFT JOIN producto p ON cp.idProducto = p.idProducto
+ WHERE c.idCategoria = ?;
+ `,
+
+ ACTUALIZAR_CATEGORIA: `
+ UPDATE categoria
+ SET nombreCategoria = ?, descripcion = ?
+ WHERE idCategoria = ?;
+ `,
+
+ ELIMINAR_PRODUCTOS_CATEGORIA: `
+ DELETE FROM categoria_producto WHERE idCategoria = ?;
+ `,
+
+ ASIGNAR_PRODUCTOS_A_CATEGORIA: `
+ INSERT INTO categoria_producto (idCategoria, idProducto)
+ VALUES ?;
+ `,
+};
diff --git a/Utilidades/Constantes/consultasClientes.js b/Utilidades/Constantes/consultasClientes.js
new file mode 100644
index 00000000..7a13ea8e
--- /dev/null
+++ b/Utilidades/Constantes/consultasClientes.js
@@ -0,0 +1,102 @@
+module.exports = {
+ OBTENER_CLIENTE: `
+ SELECT *
+ FROM cliente
+ WHERE idCliente = ?;
+ `,
+ OBTENER_LISTA: `
+ SELECT *
+ FROM cliente c
+ JOIN imagen_cliente ic ON c.idCliente = ic.idCliente
+ JOIN imagen i ON ic.idImagen = i.idImagen
+ WHERE i.tipoImagen LIKE 'Logo'
+ AND c.idCliente IN (?);
+ `,
+ ELIMINAR_CLIENTE: `
+ DELETE FROM cliente
+ WHERE idCliente = ?;
+ `,
+ VERIFICAR_NOMBRE_COMERCIAL: `
+ SELECT IF(EXISTS(SELECT nombreComercial FROM cliente WHERE nombreComercial = ?), 1, 0)`,
+
+ VERIFICAR_NOMBRE_FISCAL: `
+ SELECT IF(EXISTS(SELECT nombreFiscal FROM cliente WHERE nombreFiscal = ?), 1, 0)`,
+
+ CREAR_CLIENTE: `
+ INSERT INTO cliente (nombreComercial, nombreFiscal)
+ VALUES (?, ?)`,
+
+ CREAR_IMAGEN_CLIENTE: `
+ INSERT INTO imagen (urlImagen, tipoImagen, textoAlternativo)
+ VALUES (?, 'Logo', ?)
+ `,
+ VINCULAR_USUARIO_CLIENTE: `
+ INSERT INTO usuario_cliente (idUsuario, idCliente)
+ SELECT idUsuario, ?
+ FROM usuario_rol
+ WHERE idRol = 1;
+ `,
+
+ VINCULAR_IMAGEN_CLIENTE: `
+ INSERT INTO imagen_cliente (idImagen, idCliente)
+ VALUES (?, ?)
+`,
+
+ LEER_CLIENTE: `
+ SELECT
+ c.idCliente,
+ c.nombreComercial,
+ c.nombreFiscal,
+ (
+ SELECT COUNT(*)
+ FROM empleado e
+ WHERE e.idCliente = c.idCliente
+ ) AS numeroEmpleados,
+ (
+ SELECT COUNT(DISTINCT uc.idUsuario)
+ FROM usuario_cliente uc
+ WHERE uc.idCliente = c.idCliente
+ AND uc.idUsuario NOT IN (
+ SELECT ur.idUsuario
+ FROM usuario_rol ur
+ JOIN rol r ON ur.idRol = r.idRol
+ WHERE r.nombre = 'Empleado'
+ )
+ ) AS usuariosAsignados,
+ i.urlImagen
+ FROM
+ cliente c
+ LEFT JOIN
+ imagen_cliente ic ON c.idCliente = ic.idCliente
+ LEFT JOIN
+ imagen i ON ic.idImagen = i.idImagen AND i.tipoImagen = "Logo"
+ WHERE
+ c.idCliente = ?;
+`,
+
+ // QUERIES ACTUALIZAR
+ ACTUALIZAR_NOMBRE_FISCAL: `
+ UPDATE cliente
+ SET nombreFiscal = ?
+ WHERE idCliente = ?;
+ `,
+ ACTUALIZAR_NOMBRE_COMERCIAL: `
+ UPDATE cliente
+ SET nombreComercial = ?
+ WHERE idCliente = ?;
+ `,
+ ACTUALIZAR_AMBOS_NOMBRES: `
+ UPDATE cliente
+ SET nombreComercial = ?,
+ nombreFiscal = ?
+ WHERE idCliente = ?;
+ `,
+
+ // OBTENER EL NOMBRE DE LA IMAGEN
+ OBTENER_NOMBRE_IMAGEN: `
+ SELECT i.urlImagen
+ FROM imagen i
+ JOIN imagen_cliente ic ON i.idImagen = ic.idImagen
+ WHERE ic.idCliente = ?;
+ `,
+};
diff --git a/Utilidades/Constantes/consultasCuotas.js b/Utilidades/Constantes/consultasCuotas.js
new file mode 100644
index 00000000..3308c3d1
--- /dev/null
+++ b/Utilidades/Constantes/consultasCuotas.js
@@ -0,0 +1,83 @@
+module.exports = {
+ INSERTAR_CUOTA: `
+ INSERT INTO cuota_set (idCliente, nombre, descripcion, periodoRenovacion, renovacionHabilitada, ultimaActualizacion)
+ VALUES (?, ?, ?, ?, ?, ?)`,
+
+ SELECCIONAR_PRODUCTO: `SELECT idProducto FROM producto WHERE descripcion = ? LIMIT 1`,
+
+ INSERTAR_CUOTA_PRODUCTO: `
+ INSERT INTO cuota_set_producto (idCuotaSet, idProducto, limite, limite_actual)
+ VALUES (?, ?, ?, ?)`,
+
+ RESETEAR_LIMITES: `
+ UPDATE cuota_set_producto
+ JOIN cuota_set ON cuota_set_producto.idCuotaSet = cuota_set.idCuotaSet
+ SET cuota_set_producto.limite_actual = cuota_set_producto.limite
+ WHERE DATE_ADD(cuota_set.ultimaActualizacion, INTERVAL cuota_set.periodoRenovacion MONTH) <= CURRENT_DATE()
+ AND renovacionHabilitada = true;`,
+
+ ACTUALIZAR_FECHAS: `
+ UPDATE cuota_set
+ SET ultimaActualizacion = CURRENT_DATE()
+ WHERE DATE_ADD(ultimaActualizacion, INTERVAL periodoRenovacion MONTH) <= CURRENT_DATE();
+ `,
+
+ OBTENER_OPCIONES: `
+ SELECT idProducto as id, nombreComun as nombreProducto, tipoProducto as tipo
+ FROM producto
+ WHERE idCliente = ?;
+ `,
+ OBTENER_CUOTAS: `
+ SELECT idCuotaSet, idCliente, nombre, periodoRenovacion, renovacionHabilitada
+ FROM cuota_set
+ WHERE idCliente = ?;
+ `,
+
+ ELIMINAR_CUOTA_SET_PRODUCTO: `
+ DELETE FROM cuota_set_producto WHERE idCuotaSet = ?;
+ `,
+
+ ELIMINAR_CUOTA_SET: `
+ DELETE FROM cuota_set WHERE idCuotaSet = ?;
+ `,
+ LEER_CUOTA_SET: `
+ SELECT
+ cs.idCuotaSet,
+ cs.nombre,
+ cs.descripcion,
+ cs.periodoRenovacion,
+ cs.renovacionHabilitada,
+ cs.ultimaActualizacion
+ FROM cuota_set cs
+ WHERE cs.idCuotaSet = ?;
+ `,
+
+ LEER_CUOTA_SET_PRODUCTOS:
+ `SELECT
+ p.idProducto,
+ p.nombreComun,
+ csp.limite AS cuota_valor,
+ csp.limite_actual
+ FROM cuota_set cs
+ JOIN cuota_set_producto csp
+ ON cs.idCuotaSet = csp.idCuotaSet
+ JOIN producto p
+ ON p.idProducto = csp.idProducto
+ WHERE cs.idCuotaSet = ?`,
+
+ ACTUALIZAR_CUOTA_SET: `
+ UPDATE cuota_set
+ SET nombre = ?, descripcion = ?, periodoRenovacion = ?, renovacionHabilitada = ?, ultimaActualizacion = ?
+ WHERE idCuotaSet = ?;
+ `,
+
+ INSERTAR_CUOTA_PRODUCTO_ACTUALIZAR: `
+ INSERT INTO cuota_set_producto (idCuotaSet, idProducto, limite, limite_actual)
+ VALUES (?, ?, ?, ?)
+ `,
+
+ ELIMINAR_PRODUCTOS_CUOTA_SET: `
+ DELETE FROM cuota_set_producto WHERE idCuotaSet = ?;
+ `,
+
+};
diff --git a/Utilidades/Constantes/consultasEmpleados.js b/Utilidades/Constantes/consultasEmpleados.js
new file mode 100644
index 00000000..fa19ab29
--- /dev/null
+++ b/Utilidades/Constantes/consultasEmpleados.js
@@ -0,0 +1,81 @@
+module.exports = {
+ OBTENER_LISTA: `
+ SELECT u.idUsuario, u.nombreCompleto, u.correoElectronico, e.*
+ FROM empleado e
+ JOIN usuario u ON e.idUsuario = u.idUsuario
+ WHERE e.idCliente = ?;
+ `,
+ OBTENER_ID_USUARIO_POR_EMPLEADO: `
+ SELECT idUsuario FROM empleado WHERE idEmpleado = ?;
+ `,
+ ELIMINAR_EMPLEADO: `
+ DELETE FROM empleado
+ WHERE idEmpleado = ?;
+ `,
+ INSERTAR_EMPLEADO: `
+ INSERT INTO empleado (
+ idUsuario, idCliente, numeroEmergencia,
+ areaTrabajo, posicion, cantidadPuntos, antiguedad
+ )
+ VALUES (?, ?, ?, ?, ?, ?, ?)
+ `,
+ ACTUALIZAR: `
+ UPDATE empleado SET
+ numeroEmergencia = ?, areaTrabajo = ?, posicion = ?,
+ cantidadPuntos = ?, antiguedad = ? WHERE idEmpleado = ?;
+ `,
+ OBTENER_DATOS_EXPORTACION: `
+ SELECT
+ e.idEmpleado,
+ u.nombreCompleto,
+ u.correoElectronico,
+ u.numeroTelefono,
+ u.direccion,
+ u.fechaNacimiento,
+ u.genero,
+ CASE
+ WHEN u.estatus = 1 THEN 'Activo'
+ WHEN u.estatus = 0 THEN 'Inactivo'
+ ELSE 'Desconocido'
+ END AS estatus,
+ e.numeroEmergencia,
+ e.areaTrabajo,
+ e.posicion,
+ e.cantidadPuntos,
+ e.antiguedad
+ FROM empleado e
+ JOIN usuario u ON e.idUsuario = u.idUsuario
+ WHERE e.idCliente = ? AND e.idEmpleado IN (__IDS__);
+ `,
+ OBTENER_ULTIMO_ID_EMPLEADO: `
+ SELECT idEmpleado FROM empleado ORDER BY idEmpleado DESC LIMIT 1;
+ `,
+ CONSULTAR_ID_VALIDO: `
+ SELECT
+ CASE
+ WHEN NOT EXISTS (SELECT 1 FROM usuarios WHERE idUsuario = ?)
+ THEN 'No hay ningún usuario registrado bajo este ID'
+ WHEN EXISTS (SELECT 1 FROM empleado WHERE idUsuario = ?)
+ THEN 'Este usuario ya está registrado como empleado, revisa de nuevo el ID a usar'
+ ELSE 'OK'
+ END AS resultado;
+ `,
+
+ INSERTAR_USUARIO: `
+ INSERT INTO usuario
+ (nombreCompleto, correoElectronico, contrasenia, numeroTelefono, direccion, fechaNacimiento, genero, estatus)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+
+ `,
+
+ INSERTAR_ROL: `
+ INSERT INTO usuario_rol (idUsuario, idRol)
+ VALUES (?, ?)
+ `,
+
+ INSERTAR_USUARIO_CLIENTE: `
+ INSERT INTO usuario_cliente (idUsuario, idCliente)
+ VALUES (?, ?)
+ `,
+
+};
diff --git a/Utilidades/Constantes/consultasEventos.js b/Utilidades/Constantes/consultasEventos.js
new file mode 100644
index 00000000..022c9eca
--- /dev/null
+++ b/Utilidades/Constantes/consultasEventos.js
@@ -0,0 +1,39 @@
+module.exports = {
+ CREAR_EVENTO: `
+ INSERT INTO evento (idCliente, nombre, descripcion, puntos, multiplicador, periodoRenovacion, renovacion)
+ VALUES (?, ?, ?, ?, ?, ?, ?);
+ `,
+ VERIFICAR_CLIENTE: `
+ SELECT idCliente FROM cliente WHERE idCliente = ?;
+ `,
+ OBTENER_LISTA_EVENTOS: `
+ SELECT
+ e.idEvento,
+ e.nombre,
+ e.descripcion,
+ e.puntos,
+ e.periodoRenovacion,
+ e.renovacion
+ FROM
+ evento e
+ WHERE e.idCliente = ?
+ `,
+ ELIMINAR_EMPLEADO_EVENTO: `
+ DELETE FROM empleado_evento WHERE idEvento = ?;
+ `,
+ ELIMINAR_EVENTO: `
+ DELETE FROM evento WHERE idEvento = ?;
+ `,
+ LEER_EVENTO: `
+ SELECT
+ e.idEvento,
+ e.nombre,
+ e.descripcion,
+ e.puntos,
+ e.multiplicador,
+ e.periodoRenovacion,
+ e.renovacion
+ FROM evento e
+ WHERE e.idEvento = ?;
+ `,
+};
diff --git a/Utilidades/Constantes/consultasGrupoEmpleados.js b/Utilidades/Constantes/consultasGrupoEmpleados.js
new file mode 100644
index 00000000..ffdd2b33
--- /dev/null
+++ b/Utilidades/Constantes/consultasGrupoEmpleados.js
@@ -0,0 +1,145 @@
+module.exports = {
+ OBTENER_LISTA: `
+ SELECT ge.idGrupo,
+ ge.nombre AS geNombre,
+ ge.descripcion,
+ COUNT(eg.idEmpleado) AS totalEmpleados
+ FROM grupo_empleado ge
+ LEFT JOIN empleado_grupo eg ON ge.idGrupo = eg.idGrupo
+ WHERE ge.idCliente = ?
+ GROUP BY ge.idGrupo;
+ `,
+ ELIMINAR_SET_PRODUCTO_GRUPO: `
+ DELETE
+ FROM set_producto_grupo_empleado
+ WHERE idGrupo = ?;
+ `,
+ ELIMINAR_GRUPO: `
+ DELETE
+ FROM grupo_empleado
+ WHERE idGrupo = ?;
+ `,
+ ELIMINAR_EMPLEADO_GRUPO: `
+ DELETE
+ FROM empleado_grupo
+ WHERE idGrupo = ?;
+ `,
+ LEER_GRUPO: `
+ SELECT ge.idGrupo,
+ ge.nombre AS nombre,
+ ge.descripcion AS descripcion,
+
+ IFNULL(GROUP_CONCAT(DISTINCT sp.nombre SEPARATOR ', '), 'Sin sets de productos asociados') AS setsProductos,
+ IFNULL(GROUP_CONCAT(DISTINCT sp.idSetProducto SEPARATOR ','), '') AS idsSetProductos,
+
+ IFNULL(GROUP_CONCAT(DISTINCT CONCAT(
+ u.nombreCompleto, ' | ',
+ u.correoElectronico, ' | ',
+ e.areaTrabajo
+ ) SEPARATOR ' || '), 'Sin empleados asociados') AS infoEmpleados,
+
+ IFNULL(GROUP_CONCAT(DISTINCT e.idEmpleado SEPARATOR ','), '') AS idsEmpleados,
+ IFNULL(
+ JSON_ARRAYAGG(
+ JSON_OBJECT(
+ 'id', e.idEmpleado,
+ 'correo', u.correoElectronico,
+ 'nombre', u.nombreCompleto,
+ 'area', e.areaTrabajo
+ )
+ ),
+ JSON_ARRAY()
+ ) AS empleadosActualizar,
+ IFNULL(
+ JSON_ARRAYAGG(
+ JSON_OBJECT(
+ 'id', sp.idSetProducto,
+ 'nombreProducto', sp.nombre,
+ 'activo', sp.activo
+ )
+ ),
+ JSON_ARRAY()
+ ) AS setProductosActualizar
+ FROM grupo_empleado ge
+ LEFT JOIN empleado_grupo eg ON ge.idGrupo = eg.idGrupo
+ LEFT JOIN empleado e ON eg.idEmpleado = e.idEmpleado
+ LEFT JOIN usuario u ON e.idUsuario = u.idUsuario
+ LEFT JOIN set_producto_grupo_empleado spge ON ge.idGrupo = spge.idGrupo
+ LEFT JOIN set_producto sp ON spge.idSetProducto = sp.idSetProducto
+ WHERE ge.idGrupo = ?
+ GROUP BY ge.idGrupo
+ ORDER BY ge.idGrupo;
+ `,
+ ACTUALIZAR_GRUPO_EMPLEADOS_NOMBRE_DESCRIPCION: `
+ UPDATE grupo_empleado
+ SET nombre = ?,
+ descripcion = ?
+ WHERE idGrupo = ?
+ AND (nombre != ? OR descripcion != ?);
+ `,
+ ELIMINAR_EMPLEADOS_DE_GRUPO_BASE: `
+ DELETE
+ FROM empleado_grupo
+ WHERE idGrupo = __ID__
+ AND idEmpleado NOT IN (__EMPLEADOS__);
+ `,
+ AGREGAR_EMPLEADOS_NUEVOS_BASE: `
+ INSERT
+ IGNORE INTO empleado_grupo (idEmpleado, idGrupo)
+ VALUES __VALORES__;
+ `,
+ VERIFICAR_EMPLEADOS_CLIENTE: `
+ SELECT COUNT(*) AS validos
+ FROM empleado e
+ JOIN grupo_empleado g ON g.idGrupo = ?
+ WHERE e.idEmpleado IN (__EMPLEADOS__)
+ AND e.idCliente = g.idCliente
+ `,
+ VERIFICAR_SETS_CLIENTE: `
+ SELECT COUNT(*) AS validos
+ FROM set_producto s
+ JOIN grupo_empleado g ON g.idGrupo = ?
+ WHERE s.idSetProducto IN (__SETS__)
+ AND s.idCliente = g.idCliente
+ `,
+
+ ELIMINAR_SETS_DE_GRUPO_BASE: `
+ DELETE
+ FROM set_producto_grupo_empleado
+ WHERE idGrupo = __ID__
+ AND idSetProducto NOT IN (__SETS__);
+ `,
+
+ AGREGAR_SETS_NUEVOS_BASE: `
+ INSERT
+ IGNORE INTO set_producto_grupo_empleado (idSetProducto, idGrupo)
+ VALUES __VALORES__;
+ `,
+
+ VALIDAR_NOMBRE_REPETIDO: `
+ SELECT 1
+ FROM grupo_empleado
+ WHERE idCliente = ?
+ AND nombre = ? LIMIT 1
+ `,
+ CREAR_GRUPO: `
+ INSERT INTO grupo_empleado (idCliente, nombre, descripcion)
+ VALUES (?, ?, ?);
+ `,
+ ASIGNAR_EMPLEADO_A_GRUPO: `
+ INSERT INTO empleado_grupo (idEmpleado, idGrupo)
+ VALUES (?, ?);
+ `,
+
+ ELIMINAR_TODOS_EMPLEADOS_DE_GRUPO: `
+ DELETE
+ FROM empleado_grupo
+ WHERE idGrupo = ?;
+ `,
+
+ ELIMINAR_TODOS_SETS_DE_GRUPO: `
+ DELETE
+ FROM set_producto_grupo_empleado
+ WHERE idGrupo = ?;
+ `,
+};
\ No newline at end of file
diff --git a/Utilidades/Constantes/consultasImagenes.js b/Utilidades/Constantes/consultasImagenes.js
new file mode 100644
index 00000000..0c559a6f
--- /dev/null
+++ b/Utilidades/Constantes/consultasImagenes.js
@@ -0,0 +1,6 @@
+module.exports = {
+ CREAR: `
+ INSERT INTO imagen(urlImagen, tipoImagen, textoAlternativo)
+ VALUES (?, ?, ?);
+ `,
+};
diff --git a/Utilidades/Constantes/consultasImportarEmpleados.js b/Utilidades/Constantes/consultasImportarEmpleados.js
new file mode 100644
index 00000000..abaded26
--- /dev/null
+++ b/Utilidades/Constantes/consultasImportarEmpleados.js
@@ -0,0 +1,27 @@
+module.exports = {
+ VALIDAR_CORREOS_DUPLICADOS: `
+ SELECT correoElectronico FROM usuario WHERE correoElectronico IN (?)
+ `,
+ VALIDAR_TELEFONO_DUPLICADO: `
+ SELECT numeroTelefono FROM usuario WHERE numeroTelefono IN (?)
+ `,
+ INSERTAR_USUARIO_EN_VOLUMEN: `
+ INSERT INTO usuario
+ (nombreCompleto, correoElectronico, contrasenia, numeroTelefono, direccion, fechaNacimiento, genero, estatus)
+ VALUES ?
+ `,
+ OBTENER_ID_GENERADOS: `
+ SELECT idUsuario, correoElectronico FROM usuario WHERE correoElectronico IN (?)
+ `,
+ INSERTAR_ROLES_EN_VOLUMEN: `
+ INSERT INTO usuario_rol (idUsuario, idRol) VALUES ?
+ `,
+ INSERTAR_USUARIO_CLIENTE_EN_VOLUMEN: `
+ INSERT INTO usuario_cliente (idUsuario, idCliente) VALUES ?
+ `,
+ INSERTAR_EMPLEADOS_EN_VOLUMEN: `
+ INSERT INTO empleado
+ (idUsuario, idCliente, numeroEmergencia, areaTrabajo, posicion, cantidadPuntos, antiguedad)
+ VALUES ?
+ `,
+};
diff --git a/Utilidades/Constantes/consultasOpciones.js b/Utilidades/Constantes/consultasOpciones.js
new file mode 100644
index 00000000..825ebfe9
--- /dev/null
+++ b/Utilidades/Constantes/consultasOpciones.js
@@ -0,0 +1,6 @@
+module.exports = {
+ CREAR: `
+ INSERT INTO opcion (idVariante, cantidad, valorOpcion, SKUautomatico, SKUcomercial, costoAdicional, descuento, estado)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?);
+ `,
+};
diff --git a/Utilidades/Constantes/consultasPagos.js b/Utilidades/Constantes/consultasPagos.js
new file mode 100644
index 00000000..2a4b2f6e
--- /dev/null
+++ b/Utilidades/Constantes/consultasPagos.js
@@ -0,0 +1,8 @@
+module.exports = {
+ CONSULTAR_LISTA: `
+ SELECT idTipoPago,metodo, habilitado
+ FROM tipo_pago
+ WHERE idCliente = ?;`,
+ ACTUALIZAR: `
+ UPDATE tipo_pago SET habilitado = ? WHERE (idTipoPago = ?)`,
+};
diff --git a/Utilidades/Constantes/consultasPedidos.js b/Utilidades/Constantes/consultasPedidos.js
new file mode 100644
index 00000000..1426a12d
--- /dev/null
+++ b/Utilidades/Constantes/consultasPedidos.js
@@ -0,0 +1,49 @@
+module.exports = {
+ OBTENER_LISTA: `
+ SELECT
+ p.idPedido,
+ u.nombreCompleto AS nombreEmpleado,
+ p.fechaOrden,
+ p.estado AS estatusPedido,
+ p.precioTotal,
+ pg.estatus AS estatusPago,
+ e.estado AS estatusEnvio
+ FROM
+ pedido p
+ JOIN
+ empleado_pedido ep ON p.idPedido = ep.idPedido
+ JOIN
+ empleado em ON ep.idEmpleado = em.idEmpleado AND em.idCliente = ?
+ JOIN
+ usuario u ON em.idUsuario = u.idUsuario
+ JOIN
+ pago pg ON p.idPago = pg.idPago
+ JOIN
+ envio e ON p.idEnvio = e.idEnvio
+ ORDER BY
+ p.idPedido;`,
+
+ ELIMINAR_PEDIDO_OPCION: `
+ DELETE FROM pedido_opcion
+ WHERE idPedido = ?;`,
+
+ ELIMINAR_EMPLEADO_PEDIDO: `
+ DELETE FROM empleado_pedido
+ WHERE idPedido = ?;`,
+
+ ELIMINAR_PEDIDO: `
+ DELETE FROM pedido
+ WHERE idPedido = ?;`,
+
+ ACTUALIZAR_PEDIDO: `
+ UPDATE pedido
+ JOIN pago ON pedido.idPago = pago.idPago
+ JOIN envio ON pedido.idEnvio = envio.idEnvio
+ SET
+ pedido.estado = ?,
+ pedido.precioTotal = ?,
+ pago.estatus = ?,
+ envio.estado = ?
+ WHERE pedido.idPedido = ?;
+ `,
+};
diff --git a/Utilidades/Constantes/consultasProductos.js b/Utilidades/Constantes/consultasProductos.js
new file mode 100644
index 00000000..b3526c61
--- /dev/null
+++ b/Utilidades/Constantes/consultasProductos.js
@@ -0,0 +1,125 @@
+module.exports = {
+ OBTENER_LISTA: `
+ SELECT p.idProducto, p.nombreComun, p.precioVenta, p.estado, i.urlImagen
+ FROM producto p
+ LEFT JOIN imagen_producto ip ON p.idProducto = ip.idProducto
+ LEFT JOIN imagen i ON ip.idImagen = i.idImagen AND i.tipoImagen = "Imagen Producto"
+ WHERE p.idCliente = ?;
+ `,
+ CREAR: `
+ INSERT INTO producto (idCliente, idProveedor, nombreComun, nombreComercial, descripcion,
+ marca, modelo, tipoProducto, precioPuntos, precioCliente,
+ precioVenta, costo, impuesto, descuento, estado, envio)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
+ `,
+ CREAR_IMAGEN_PRODUCTO: `
+ INSERT INTO imagen_producto (idImagen, idProducto)
+ VALUES (?, ?);
+ `,
+ CREAR_DATOS_ENVIO: `
+ INSERT INTO datos_envio (idProducto, peso, longitud, ancho, altura, volumen, tipoPaquete)
+ VALUES (?, ?, ?, ?, ?, ?, ?);
+ `,
+
+ ELIMINAR_PRODUCTOS:
+ "DELETE FROM producto WHERE idProducto IN (?)",
+
+ OBTENER_IMAGENES_POR_IDS: `
+ SELECT p.idProducto, i.urlImagen
+ FROM producto p
+ LEFT JOIN imagen_producto ip ON p.idProducto = ip.idProducto
+ LEFT JOIN imagen i ON ip.idImagen = i.idImagen
+ WHERE p.idProducto IN (?);
+ `,
+
+ LEER_PRODUCTO: `
+ SELECT JSON_OBJECT(
+ 'idProducto', p.idProducto,
+ 'idProveedor', p.idProveedor,
+ 'nombreComun', p.nombreComun,
+ 'nombreComercial', p.nombreComercial,
+ 'marca', p.marca,
+ 'modelo', p.modelo,
+ 'tipoProducto', p.tipoProducto,
+ 'precioPuntos', p.precioPuntos,
+ 'precioCliente', p.precioCliente,
+ 'precioVenta', p.precioVenta,
+ 'costo', p.costo,
+ 'impuesto', p.impuesto,
+ 'descuento', p.descuento,
+ 'estado', p.estado,
+ 'envio', p.envio,
+ 'nombreProveedor', pr.nombreCompania,
+ 'variantes', (SELECT JSON_ARRAYAGG(
+ JSON_OBJECT(
+ 'idVariante', v.idVariante,
+ 'nombreVariante', v.nombreVariante,
+ 'descripcion', v.descripcion,
+ 'opciones', (SELECT JSON_ARRAYAGG(
+ JSON_OBJECT(
+ 'cantidad', o.cantidad,
+ 'valorOpcion',
+ o.valorOpcion,
+ 'SKUautomatico',
+ o.SKUautomatico,
+ 'SKUcomercial',
+ o.SKUcomercial,
+ 'costoAdicional',
+ o.costoAdicional,
+ 'descuento', o.descuento,
+ 'estado', o.estado
+ )
+ )
+ FROM opcion o
+ WHERE o.idVariante = v.idVariante)
+ )
+ )
+ FROM variante v
+ WHERE v.idProducto = p.idProducto)
+ ) AS producto
+ FROM producto p
+ LEFT JOIN proveedor pr ON p.idProveedor = pr.idProveedor
+ WHERE p.idProducto = ?
+ AND p.idCliente = ?;
+ `,
+ OBTENER_DATOS_EXPORTACION: `
+ SELECT
+ p.idProducto,
+ p.idProveedor,
+ p.nombreComun AS nombreProducto,
+ p.nombreComercial,
+ p.descripcion AS descripcionProducto,
+ p.tipoProducto,
+ p.marca,
+ p.modelo,
+ p.costo,
+ p.precioVenta,
+ p.precioCliente,
+ p.precioPuntos,
+ p.impuesto,
+ p.descuento,
+ p.estado,
+ p.envio,
+ GROUP_CONCAT(
+ CONCAT(
+ v.nombreVariante, '-',
+ v.descripcion, ',',
+ (SELECT GROUP_CONCAT(
+ CONCAT(o.valorOpcion, ':', o.SKUcomercial, ':', o.SKUautomatico, ':', o.cantidad)
+ SEPARATOR ', '
+ )
+ FROM opcion o
+ WHERE o.idVariante = v.idVariante
+ )
+ )
+ SEPARATOR ' | '
+ ) AS variantes_opciones
+ FROM producto p
+ JOIN variante v ON v.idProducto = p.idProducto
+ WHERE p.idCliente = ? AND p.idProducto IN (__IDS__)
+ GROUP BY p.idProducto, p.idProveedor, p.nombreComun, p.nombreComercial,
+ p.descripcion, p.tipoProducto, p.marca, p.modelo, p.costo,
+ p.precioVenta, p.precioCliente, p.precioPuntos, p.impuesto,
+ p.descuento, p.estado, p.envio;
+ `,
+};
diff --git a/Utilidades/Constantes/consultasProveedores.js b/Utilidades/Constantes/consultasProveedores.js
new file mode 100644
index 00000000..95edd293
--- /dev/null
+++ b/Utilidades/Constantes/consultasProveedores.js
@@ -0,0 +1,14 @@
+module.exports = {
+ OBTENER_LISTA: `
+ SELECT * FROM proveedor
+ WHERE idCliente = ?;
+ `,
+ CREAR: `
+ INSERT INTO proveedor (idCliente, nombre, nombreCompania, telefonoContacto, direccion, codigoPostal, pais, estado)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?);
+ `,
+ VERIFICAR_EXISTE:`
+ SELECT idProveedor FROM proveedor WHERE idProveedor = ? LIMIT 1
+ `
+}
+
diff --git a/Utilidades/Constantes/consultasRoles.js b/Utilidades/Constantes/consultasRoles.js
new file mode 100644
index 00000000..3f6de048
--- /dev/null
+++ b/Utilidades/Constantes/consultasRoles.js
@@ -0,0 +1,91 @@
+/**
+ * @file consultasRoles.js
+ * @description
+ * Contiene las consultas SQL utilizadas en el backend para interactuar con la entidad "Rol".
+ * Estas consultas se utilizan principalmente en el repositorio de roles para realizar operaciones
+ * de lectura sobre la base de datos.
+ *
+ * @exports OBTENER_LISTA Consulta SQL que permite obtener todos los roles registrados,
+ * junto con la cantidad de usuarios asociados a cada uno.
+ */
+
+module.exports = {
+ /**
+ * Consulta SQL para obtener la lista de roles del sistema.
+ *
+ * @constant
+ * @type {string}
+ *
+ * @returns {Object[]} Lista de roles con:
+ * - idRol: Identificador único del rol.
+ * - nombre: Nombre del rol.
+ * - descripcion: Descripción del rol.
+ * - totalUsuarios: Número de usuarios asociados al rol.
+ *
+ * @description
+ * Realiza un LEFT JOIN entre las tablas `Rol` y `Usuario_Rol` para contabilizar
+ * cuántos usuarios están relacionados con cada rol.
+ * Agrupa los resultados por `idRol` para consolidar la información por rol.
+ */
+ OBTENER_LISTA: `
+ SELECT r.idRol, r.nombre, r.descripcion, COUNT(ur.idUsuario) AS totalUsuarios
+ FROM rol r
+ LEFT JOIN usuario_rol ur ON r.idRol = ur.idRol
+ GROUP BY r.idRol;
+ `,
+ VERIFICAR_NOMBRE_ROL: `
+ SELECT idRol
+ FROM rol
+ WHERE nombre = ? LIMIT 1`,
+
+ VERIFICAR_PERMISO: `
+ SELECT idPermiso
+ FROM permiso
+ WHERE idPermiso = ? LIMIT 1`,
+
+ INSERTAR_ROL: `
+ INSERT INTO rol (nombre, descripcion)
+ VALUES (?, ?)`,
+
+ INSERTAR_ROL_PERMISO: `
+ INSERT INTO rol_permiso (idRol, idPermiso)
+ VALUES (?, ?)`,
+
+ OBTENER_PERMISOS_POR_CLIENTE: `
+ SELECT idPermiso AS id, nombre
+ FROM permiso;
+ `,
+
+ ELIMINAR_ROL: `
+ DELETE
+ FROM rol
+ WHERE idRol IN (__IDS__);
+ `,
+ VALIDAR_ROL_SIN_USUARIOS: `
+ SELECT COUNT(*) AS cantidad
+ FROM usuario_rol
+ WHERE idRol IN (__IDS__);
+ `,
+ OBTENER_DETALLE_ROL: `
+ SELECT r.idRol,
+ r.nombre AS nombreRol,
+ r.descripcion AS descripcionRol,
+ (SELECT COUNT(*)
+ FROM usuario_rol ur
+ WHERE ur.idRol = r.idRol) AS totalUsuarios,
+ p.idPermiso,
+ p.nombre AS nombrePermiso,
+ p.descripcion AS descripcionPermiso
+ FROM rol r
+ LEFT JOIN rol_permiso rp ON r.idRol = rp.idRol
+ LEFT JOIN permiso p ON rp.idPermiso = p.idPermiso
+ WHERE r.idRol = ?;
+ `,
+
+ VERIFICAR_NOMBRE_DUPLICADO_ROL: `
+ select *
+ from rol
+ where nombre = ?;
+ `,
+
+};
\ No newline at end of file
diff --git a/Utilidades/Constantes/consultasSetsProductos.js b/Utilidades/Constantes/consultasSetsProductos.js
new file mode 100644
index 00000000..07a20c80
--- /dev/null
+++ b/Utilidades/Constantes/consultasSetsProductos.js
@@ -0,0 +1,78 @@
+module.exports = {
+ OBTENER_LISTA: `
+ SELECT sp.idSetProducto,
+ sp.nombre,
+ sp.descripcion,
+ sp.activo,
+ GROUP_CONCAT(DISTINCT p.nombreComun SEPARATOR ', ') AS productos,
+ GROUP_CONCAT(DISTINCT ge.nombre SEPARATOR ', ') AS grupos,
+ GROUP_CONCAT(p.idProducto SEPARATOR ', ') AS idsProductos
+ FROM set_producto sp
+ LEFT JOIN producto_set_producto psp ON psp.idSetProducto = sp.idSetProducto
+ LEFT JOIN producto p ON p.idProducto = psp.idProducto
+ LEFT JOIN set_producto_grupo_empleado spge ON spge.idSetProducto = sp.idSetProducto
+ LEFT JOIN grupo_empleado ge ON ge.idGrupo = spge.idGrupo
+ WHERE sp.idCliente = ?
+ GROUP BY sp.idSetProducto, sp.nombre, sp.descripcion, sp.activo;
+ `,
+ ELIMINAR_SET_PRODUCTOS_GRUPO_EMPLEADOS: `
+ DELETE
+ FROM set_producto_grupo_empleado
+ WHERE idSetProducto = ?;
+ `,
+ ELIMINAR_PRODUCTOS_SET_PRODUCTOS: `
+ DELETE
+ FROM producto_set_producto
+ WHERE idSetProducto = ?;
+ `,
+ ELIMINAR_SET_PRODUCTOS: `
+ DELETE
+ FROM set_producto
+ WHERE idSetProducto = ?;
+ `,
+ CREAR_SET_PRODUCTO: `
+ INSERT INTO set_producto (idCliente, nombre, nombreVisible, descripcion, activo)
+ VALUES (?, ?, ?, ?, ?);
+ `,
+ ASIGNAR_PRODUCTO_SET_PRODUCTO: `
+ INSERT INTO producto_set_producto (idProducto, idSetProducto)
+ VALUES (?, ?);
+ `,
+ CONSULTAR_DUPLICADOS: `
+ SELECT idSetProducto
+ FROM set_producto
+ WHERE idCliente = ?
+ AND (nombre = ? OR nombreVisible = ?);
+ `,
+ CONSULTAR_NOMBRE_DUPLICADO: `
+ SELECT idSetProducto
+ FROM set_producto
+ WHERE idCliente = ? and idSetProducto!= ?
+ AND (nombre = ?);
+ `,
+ CONSULTAR_PRODUCTOS_EXISTENTES: `
+ SELECT idProducto
+ FROM producto
+ WHERE idProducto IN (__IDS__);
+ `,
+ ACTUALIZAR_SET_INFO: `
+ UPDATE set_producto
+ SET nombre = ?, activo = ?, descripcion = ?
+ WHERE idSetProducto = ?
+ `,
+
+ ELIMINAR_PRODUCTOS_DEL_SET: `
+ DELETE FROM producto_set_producto
+ WHERE idSetProducto = __ID__ AND idProducto NOT IN (__PRODUCTOS__)
+ `,
+
+ AGREGAR_PRODUCTOS_AL_SET: `
+ INSERT IGNORE INTO producto_set_producto (idSetProducto, idProducto)
+ VALUES __VALORES__
+ `,
+
+ ELIMINAR_TODOS_PRODUCTOS_DEL_SET: `
+ DELETE FROM producto_set_producto
+ WHERE idSetProducto = ?
+ `,
+};
diff --git a/Utilidades/Constantes/consultasUsuarios.js b/Utilidades/Constantes/consultasUsuarios.js
new file mode 100644
index 00000000..0f679e91
--- /dev/null
+++ b/Utilidades/Constantes/consultasUsuarios.js
@@ -0,0 +1,188 @@
+module.exports = {
+ OBTENER_USUARIO: `
+ SELECT *
+ FROM usuario u
+ WHERE u.correoElectronico = ?
+ AND u.estatus = true;
+ `,
+
+ OBTENER_CLIENTES_ASOCIADOS: `
+ SELECT uc.idCliente
+ FROM usuario u
+ JOIN usuario_cliente uc ON u.idUsuario = uc.idUsuario
+ WHERE u.correoElectronico = ?;
+ `,
+
+ OBTENER_PERMISOS: `
+ SELECT p.nombre
+ FROM usuario u
+ JOIN usuario_rol ur ON ur.idUsuario = u.idUsuario
+ JOIN rol r ON ur.idRol = r.idRol
+ JOIN rol_permiso rp ON rp.idRol = r.idRol
+ JOIN permiso p ON rp.idPermiso = p.idPermiso
+ WHERE u.correoElectronico = ?;
+ `,
+
+ CREAR_USUARIO: `
+ INSERT INTO usuario (nombreCompleto,
+ correoElectronico,
+ contrasenia,
+ numeroTelefono,
+ direccion,
+ fechaNacimiento,
+ genero,
+ estatus)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?);
+ `,
+
+ ASIGNAR_ROL_A_USUARIO: `
+ INSERT INTO usuario_rol (idUsuario, idRol)
+ VALUES (?, ?);
+ `,
+
+ ASOCIAR_USUARIO_A_CLIENTE: `
+ INSERT INTO usuario_cliente (idUsuario, idCliente)
+ VALUES (?, ?);
+ `,
+
+ LEER_USUARIO: `
+ SELECT u.idUsuario,
+ u.nombreCompleto,
+ u.correoElectronico,
+ u.numeroTelefono,
+ u.direccion,
+ u.fechaNacimiento,
+ u.genero,
+ u.estatus,
+ r.nombre AS rol,
+ uc.idCliente,
+ c.nombreComercial AS nombreCliente
+ FROM usuario u
+ LEFT JOIN usuario_rol ur ON u.idUsuario = ur.idUsuario
+ LEFT JOIN rol r ON ur.idRol = r.idRol
+ LEFT JOIN usuario_cliente uc ON u.idUsuario = uc.idUsuario
+ LEFT JOIN cliente c ON uc.idCliente = c.idCliente
+ WHERE u.idUsuario = ?;
+ `,
+
+ OBTENER_LISTA: `
+ SELECT u.idUsuario,
+ u.nombreCompleto AS nombre,
+ r.nombre AS rol,
+ c.nombreComercial AS cliente,
+ u.estatus,
+ u.correoElectronico AS correo,
+ u.numeroTelefono AS telefono
+ FROM usuario u
+ LEFT JOIN usuario_rol ur ON u.idUsuario = ur.idUsuario
+ LEFT JOIN rol r ON ur.idRol = r.idRol
+ LEFT JOIN usuario_cliente uc ON u.idUsuario = uc.idUsuario
+ LEFT JOIN cliente c ON uc.idCliente = c.idCliente
+ WHERE u.idUsuario NOT IN (SELECT ur2.idUsuario
+ FROM usuario_rol ur2
+ WHERE ur2.idRol = 3);
+
+ `,
+
+ ELIMINAR_USUARIOS: `
+ DELETE
+ FROM usuario
+ WHERE idUsuario = (?);
+ `,
+ VALIDAR_CORREO: `
+ SELECT idUsuario
+ FROM usuario
+ WHERE correoElectronico = ?;
+ `,
+ VALIDAR_TELEFONO: `
+ SELECT idUsuario
+ FROM usuario
+ WHERE numeroTelefono = ?;`,
+
+ OBTENER_EMPLEADOS_POR_USUARIOS: `
+ SELECT idEmpleado
+ FROM empleado
+ WHERE idUsuario IN (?);
+ `,
+
+ ELIMINAR_CUOTA_SET_GRUPO_EMPLEADO: `
+ DELETE
+ FROM cuota_set_grupo_empleado
+ WHERE idEmpleado IN (?);
+ `,
+
+ ELIMINAR_EMPLEADO_EVENTO: `
+ DELETE
+ FROM empleado_evento
+ WHERE idEmpleado IN (?);
+ `,
+
+ ELIMINAR_EMPLEADO_GRUPO: `
+ DELETE
+ FROM empleado_grupo
+ WHERE idEmpleado IN (?);
+ `,
+
+ ELIMINAR_EMPLEADO_PEDIDO: `
+ DELETE
+ FROM empleado_pedido
+ WHERE idEmpleado IN (?);
+ `,
+
+ ELIMINAR_TIPO_PAGO_EMPLEADO: `
+ DELETE
+ FROM tipo_pago_empleado
+ WHERE idEmpleado IN (?);
+ `,
+
+ OBTENER_CARRITOS_POR_USUARIOS: `
+ SELECT idCarrito
+ FROM carrito
+ WHERE idUsuario IN (?);
+ `,
+
+ ELIMINAR_CARRITO_OPCION: `
+ DELETE
+ FROM carrito_opcion
+ WHERE idCarrito IN (?);
+ `,
+
+ ELIMINAR_CARRITO_POR_USUARIOS: `
+ DELETE
+ FROM carrito
+ WHERE idUsuario IN (?);
+ `,
+
+ ELIMINAR_USUARIO_ROL: `
+ DELETE
+ FROM usuario_rol
+ WHERE idUsuario IN (?);
+ `,
+
+ ELIMINAR_USUARIO_CLIENTE: `
+ DELETE
+ FROM usuario_cliente
+ WHERE idUsuario IN (?);
+ `,
+
+ ELIMINAR_EMPLEADO_POR_USUARIOS: `
+ DELETE
+ FROM empleado
+ WHERE idUsuario IN (?);
+ `,
+
+ ELIMINAR_USUARIOS_POR_IDS: `
+ DELETE
+ FROM usuario
+ WHERE idUsuario IN (?);
+ `,
+
+ CONSULTAR_USUARIOS_PROTEGIDOS: `
+ SELECT idUsuario
+ FROM usuarios_2fa
+ WHERE idUsuario IN (?)
+ AND puedeActivar2FA = true;
+ `,
+
+
+};
diff --git a/Utilidades/Constantes/consultasVariantes.js b/Utilidades/Constantes/consultasVariantes.js
new file mode 100644
index 00000000..b9ebc210
--- /dev/null
+++ b/Utilidades/Constantes/consultasVariantes.js
@@ -0,0 +1,10 @@
+module.exports = {
+ CREAR: `
+ INSERT INTO variante (idProducto, nombreVariante, descripcion)
+ VALUES (?, ?, ?);
+ `,
+ CREAR_IMAGEN_VARIANTE: `
+ INSERT INTO imagen_variante (idImagen, idVariante)
+ VALUES (?, ?);
+ `,
+};
diff --git a/Utilidades/Constantes/mensajesAutenticacion.js b/Utilidades/Constantes/mensajesAutenticacion.js
new file mode 100644
index 00000000..59ee6fc1
--- /dev/null
+++ b/Utilidades/Constantes/mensajesAutenticacion.js
@@ -0,0 +1,107 @@
+module.exports = {
+ // 200 - OK
+ INICIO_SESION_EXITOSO: {
+ codigo: 200,
+ mensaje: "Inicio de sesión exitoso.",
+ },
+ CIERRE_SESION_EXITOSO: {
+ codigo: 200,
+ mensaje: "Sesión cerrada correctamente.",
+ },
+
+ // 201 - Created
+ REGISTRO_ACCESO_EXITOSO: {
+ codigo: 201,
+ mensaje: "Acceso registrado exitosamente.",
+ },
+
+ // 204 - No Content
+ SESION_NO_EXISTENTE: {
+ codigo: 204,
+ mensaje: "No había sesión activa para cerrar.",
+ },
+
+ // 400 - Bad Request
+ CAMPOS_OBLIGATORIOS: {
+ codigo: 400,
+ mensaje: "Se necesita ingresar correo y contraseña.",
+ },
+ FORMATO_CORREO_INVALIDO: {
+ codigo: 400,
+ mensaje: "El formato del correo electrónico no es válido.",
+ },
+ CONTRASENIA_NO_SEGURA: {
+ codigo: 400,
+ mensaje: "La contraseña no cumple con los criterios de seguridad.",
+ },
+ TOKEN_NO_PROPORCIONADO: {
+ codigo: 400,
+ mensaje: "No se proporcionó un token de autenticación.",
+ },
+
+ // 401 - Unauthorized
+ CREDENCIALES_INVALIDAS: {
+ codigo: 401,
+ mensaje: "Usuario o contraseña incorrectos.",
+ },
+ USUARIO_NO_AUTENTICADO: {
+ codigo: 401,
+ mensaje: "No se ha iniciado sesión.",
+ },
+ TOKEN_INVALIDO: {
+ codigo: 401,
+ mensaje: "El token proporcionado no es válido.",
+ },
+ TOKEN_EXPIRADO: {
+ codigo: 401,
+ mensaje: "La sesión ha expirado. Por favor, inicie sesión nuevamente.",
+ },
+ TOKEN_CORRUPTO: {
+ codigo: 401,
+ mensaje: "El token está dañado o tiene un formato incorrecto.",
+ },
+ API_KEY_INVALIDA: {
+ codigo: 401,
+ mensaje: "API Key inválida o no proporcionada.",
+ },
+
+ // 403 - Forbidden
+ ACCESO_NO_AUTORIZADO: {
+ codigo: 403,
+ mensaje: "No tiene permisos para acceder a este recurso.",
+ },
+
+ // 404 - Not Found
+ USUARIO_NO_ENCONTRADO: {
+ codigo: 404,
+ mensaje: "No se encontró un usuario con ese correo electrónico.",
+ },
+
+ // 409 - Conflict
+ SESION_YA_INICIADA: {
+ codigo: 409,
+ mensaje: "Ya hay una sesión iniciada en este dispositivo.",
+ },
+
+ // 500 - Internal Server Error
+ ERROR_SERVIDOR: {
+ codigo: 500,
+ mensaje: "Ocurrió un error inesperado. Intente de nuevo más tarde.",
+ },
+ ERROR_OBTENER_USUARIO: {
+ codigo: 500,
+ mensaje: "Error al obtener datos del usuario.",
+ },
+ ERROR_GENERAR_TOKEN: {
+ codigo: 500,
+ mensaje: "No se pudo generar el token de autenticación.",
+ },
+ ERROR_CIERRE_SESION: {
+ codigo: 500,
+ mensaje: "Hubo un problema al cerrar la sesión.",
+ },
+ ERROR_VALIDAR_TOKEN: {
+ codigo: 500,
+ mensaje: "Hubo un problema al validar el token.",
+ },
+};
diff --git a/Utilidades/Constantes/mensajesCategorias.js b/Utilidades/Constantes/mensajesCategorias.js
new file mode 100644
index 00000000..3629a3f0
--- /dev/null
+++ b/Utilidades/Constantes/mensajesCategorias.js
@@ -0,0 +1,90 @@
+module.exports = {
+ // 201 - Creado
+ CATEGORIA_CREADA: {
+ codigo: 201,
+ mensaje: 'Categoría creada correctamente.',
+ },
+
+ // 200 - OK
+ CATEGORIA_OBTENIDA: {
+ codigo: 200,
+ mensaje: 'Información de la categoría obtenida exitosamente.',
+ },
+ LISTA_CATEGORIAS_OBTENIDA: {
+ codigo: 200,
+ mensaje: 'Lista de categorías obtenida exitosamente.',
+ },
+ CATEGORIA_ELIMINADA: {
+ codigo: 200,
+ mensaje: 'Categoría eliminada correctamente.',
+ },
+
+ // 204 - Sin contenido
+ CATEGORIAS_NO_ENCONTRADAS: {
+ codigo: 204,
+ mensaje: 'No se encontraron categorías registradas.',
+ },
+
+ // 400 - Bad Request
+ DATOS_INCOMPLETOS: {
+ codigo: 400,
+ mensaje: 'Faltan campos requeridos para crear la categoría.',
+ },
+ NOMBRE_CATEGORIA_INVALIDO: {
+ codigo: 400,
+ mensaje: 'El nombre de la categoría es obligatorio.',
+ },
+ CATEGORIA_YA_EXISTE: {
+ codigo: 400,
+ mensaje: 'Ya existe una categoría con ese nombre.',
+ },
+ PARAMETROS_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Los parámetros proporcionados no son válidos.',
+ },
+ ERROR_OBTENER_CATEGORIAS: {
+ codigo: 400,
+ mensaje: 'Ocurrió un error al obtener la lista de categorías.',
+ },
+
+ // 401 - No autorizado
+ CREDENCIALES_INVALIDAS: {
+ codigo: 401,
+ mensaje: 'Credenciales inválidas para consultar categorías.',
+ },
+
+ // 403 - Acceso denegado
+ ACCESO_DENEGADO: {
+ codigo: 403,
+ mensaje: 'No tiene permiso para realizar esta acción sobre categorías.',
+ },
+
+ // 404 - No encontrado
+ CATEGORIA_NO_ENCONTRADA: {
+ codigo: 404,
+ mensaje: 'No se encontró una categoría con el ID proporcionado.',
+ },
+
+ // 500 - Error del servidor
+ ERROR_CREAR_CATEGORIA: {
+ codigo: 400,
+ mensaje: 'Ocurrió un error al intentar crear la categoría.',
+ },
+ ERROR_OBTENER_CATEGORIA: {
+ codigo: 400,
+ mensaje: 'Ocurrió un error al obtener los datos de la categoría.',
+ },
+ ERROR_ELIMINAR_CATEGORIA: {
+ codigo: 400,
+ mensaje: 'Ocurrió un error al eliminar la categoría.',
+ },
+ PRODUCTO_NO_EXISTE: {
+ codigo: 400,
+ mensaje: 'El producto no existe en la base de datos',
+ },
+ DESCRIPCION_INVALIDA: {
+ codigo: 400,
+ mensaje: 'La descripción proporcionada no es válida.',
+ },
+
+};
diff --git a/Utilidades/Constantes/mensajesClientes.js b/Utilidades/Constantes/mensajesClientes.js
new file mode 100644
index 00000000..3e5ea4e5
--- /dev/null
+++ b/Utilidades/Constantes/mensajesClientes.js
@@ -0,0 +1,112 @@
+module.exports = {
+ // 200 - OK
+ CONSULTA_EXITOSA: {
+ codigo: 200,
+ mensaje: 'Información del cliente obtenida exitosamente.',
+ },
+ CONSULTA_LISTA_EXITOSA: {
+ codigo: 200,
+ mensaje: 'Lista de clientes obtenida exitosamente.',
+ },
+ CLIENTE_ELIMINADO: {
+ codigo: 200,
+ mensaje: 'Cliente eliminado exitosamente.',
+ },
+
+ // 204 - No Content
+ CLIENTE_SIN_SISTEMA: {
+ codigo: 204,
+ mensaje: 'El cliente no tiene un sistema registrado.',
+ },
+ LISTA_CLIENTES_VACIA: {
+ codigo: 204,
+ mensaje: 'No hay clientes registrados actualmente.',
+ },
+
+ // 400 - Bad Request
+ PARAMETROS_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Los parámetros proporcionados no son válidos o están incompletos.',
+ },
+ FORMATO_ID_CLIENTE_INVALIDO: {
+ codigo: 400,
+ mensaje: 'El formato del ID del cliente debe ser un número entero válido.',
+ },
+ LISTA_CLIENTES_INVALIDA: {
+ codigo: 400,
+ mensaje: 'La lista de clientes asociados es inválida o no contiene IDs numéricos válidos.',
+ },
+ CLIENTES_ASOCIADOS_NO_PROPORCIONADOS: {
+ codigo: 400,
+ mensaje: 'No se proporcionó la lista de clientes asociados.',
+ },
+ CLIENTE_INVALIDO: {
+ codigo: 400,
+ mensaje: 'El ID del cliente debe ser un número entero válido.',
+ },
+ ERROR_ELIMINAR_CLIENTE: {
+ codigo: 400,
+ mensaje: 'Ocurrió un error al eliminar el cliente.',
+ },
+ ERROR_CONSULTAR_CLIENTE: {
+ codigo: 400,
+ mensaje: 'Ocurrió un error al obtener la información del cliente.',
+ },
+
+ // 403 - Forbidden
+ ACCESO_NO_AUTORIZADO: {
+ codigo: 403,
+ mensaje: 'No tiene permiso para consultar la información de este cliente.',
+ },
+
+ // 404 - Not Found
+ CLIENTE_NO_ENCONTRADO: {
+ codigo: 404,
+ mensaje: 'No se encontró un cliente con el ID proporcionado.',
+ },
+ SISTEMA_NO_ENCONTRADO: {
+ codigo: 404,
+ mensaje: 'No se encontró el sistema asociado al cliente.',
+ },
+
+ // 500 - Internal Server Error
+ ERROR_CONSULTAR_SISTEMA: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al obtener la información del sistema del cliente.',
+ },
+ ERROR_CONSULTAR_LISTA_CLIENTES: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al obtener la lista de clientes.',
+ },
+
+
+ // Crear cliente
+ CAMPO_OBLIGATORIO: {
+ codigo: 400,
+ mensaje: 'Ingresa el nombre fiscal, nombre comercial y la imagen.',
+ },
+ CLIENTE_COMERCIAL_EXISTENTE: {
+ codigo: 400,
+ mensaje: 'Ya existe un cliente con el mismo nombre comercial.',
+ },
+ CLIENTE_FISCAL_EXISTENTE: {
+ codigo: 400,
+ mensaje: 'Ya existe un cliente con el mismo nombre legal.',
+ },
+ CLIENTE_CREADO: {
+ codigo: 201,
+ mensaje: 'Cliente creado con éxito.',
+ },
+ ERROR_CREACION: {
+ codigo: 500,
+ mensaje: 'Error al crear cliente.',
+ },
+ CLIENTE_ACTUALIZADO: {
+ codigo: 200,
+ mensaje: 'Cliente actualizado correctamente.',
+ },
+ ERROR_CLIENTE_ACTUALIZADO: {
+ codigo: 400,
+ mensaje: 'Error actualizando cliente.',
+ },
+};
diff --git a/Utilidades/Constantes/mensajesCuotas.js b/Utilidades/Constantes/mensajesCuotas.js
new file mode 100644
index 00000000..9ac28661
--- /dev/null
+++ b/Utilidades/Constantes/mensajesCuotas.js
@@ -0,0 +1,72 @@
+// mensajesCuotas.js
+
+module.exports = {
+ // crearCuota
+ FORMATO_INVALIDO: 'Formato de cuota set inválido',
+ CREACION_EXITOSA: 'Cuota set creado exitosamente',
+ ERROR_CREACION: 'Error creando cuota set',
+
+ // obtenerOpcionesCuotas
+ FALTA_ID_CLIENTE: 'No hay idCliente',
+ OPCIONES_OBTENIDAS: 'Opciones producto para cuota',
+ ERROR_OBTENIENDO_OPCIONES: 'Error obteniendo opciones',
+
+ // validarCuotaSet
+ NOMBRE_REQUERIDO: 'El campo "nombre" es obligatorio.',
+ PRODUCTOS_REQUERIDOS: 'Debes enviar al menos un producto con su límite.',
+ ID_PRODUCTO_INVALIDO: (pos) => `El producto en la posición ${pos} no tiene un idProducto válido.`,
+ LIMITE_INVALIDO: (id) => `El producto "${id}" tiene un "limite" inválido.`,
+ LIMITE_ACTUAL_INVALIDO: (id) => `El producto "${id}" tiene un "limiteActual" inválido.`,
+
+ // consultarListaCuotas
+ CONSULTA_EXITOSA: {
+ codigo: 200,
+ mensaje: 'Lista de sets de cuotas obtenida exitosamente.',
+ },
+
+ SIN_RESULTADOS: {
+ codigo: 204,
+ mensaje: 'No se encontraron sets de cuotas registrados para el cliente.',
+ },
+
+ PARAMETROS_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Falta el ID del cliente para realizar la consulta.',
+ },
+
+ ERROR_CONSULTAR_CUOTAS: {
+ codigo: 500,
+ mensaje: 'Error al consultar los sets de cuotas.',
+ },
+
+ SET_CUOTA_NO_ENCONTRADO: {
+ codigo: 404,
+ mensaje: 'Set de cuotas no encontrado.',
+ },
+
+ SET_CUOTA_ELIMINADO: {
+ codigo: 200,
+ mensaje: 'Set de cuotas eliminado correctamente.',
+ },
+
+ ERROR_ELIMINAR_SET_CUOTAS: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al eliminar el set de productos.',
+ },
+
+ ERROR_OBTENER_SET_CUOTA: {
+ codigo: 500,
+ mensaje: 'Error interno al obtener el set de cuotas.',
+ },
+
+ ACTUALIZACION_EXITOSA: {
+ codigo: 200,
+ mensaje: 'Set de cuotas actualizado correctamente.'
+ },
+
+ ERROR_ACTUALIZACION: {
+ codigo: 500,
+ mensaje: 'No se pudo actualizar el set de cuotas.'
+ },
+
+};
diff --git a/Utilidades/Constantes/mensajesEmpleados.js b/Utilidades/Constantes/mensajesEmpleados.js
new file mode 100644
index 00000000..dcb3049b
--- /dev/null
+++ b/Utilidades/Constantes/mensajesEmpleados.js
@@ -0,0 +1,108 @@
+module.exports = {
+ // 200 - OK
+ EXITO_CREAR: {
+ codigo: 200,
+ mensaje: 'Empleado agregado exitosamente.',
+ },
+ CONSULTA_EXITOSA: {
+ codigo: 200,
+ mensaje: 'Lista de empleados obtenida exitosamente.',
+ },
+ EXITO_ACTUALIZAR: {
+ codigo: 200,
+ mensaje: 'Actualización exitosa.',
+ },
+
+ // 204 - No Content
+ SIN_RESULTADOS: {
+ codigo: 204,
+ mensaje: 'No se encontraron empleados registrados para el cliente.',
+ },
+
+ // 400 - Bad Request
+ PARAMETROS_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Los parámetros proporcionados no son válidos o están incompletos.',
+ },
+ LIMITE_OFFSET_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Los valores de límite u offset deben ser números positivos.',
+ },
+ ERROR_ACTUALIZAR: {
+ codigo: 400,
+ mensaje: 'Error al actualizar',
+ },
+ ERROR_EXPORTAR_EMPLEADOS: {
+ codigo: 400,
+ mensaje: 'Error al exportar la lista de empleados.',
+ },
+ ERROR_CREAR: {
+ codigo: 400,
+ mensaje: 'Error al crear',
+ },
+ CAMPOS_REQUERIDOS: {
+ codigo: 400,
+ mensaje: 'Faltan campos requeridos',
+ },
+
+ // 403 - Forbidden
+ PERMISO_DENEGADO: {
+ codigo: 403,
+ mensaje: 'No tiene permiso para consultar empleados de este cliente.',
+ },
+
+ // 500 - Internal Server Error
+ ERROR_CONSULTAR_EMPLEADOS: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al obtener la lista de empleados.',
+ },
+ // 404 - Not Found
+ EMPLEADO_NO_ENCONTRADO: {
+ codigo: 404,
+ mensaje: 'No se encontró el empleado especificado.',
+ },
+ // 200 - OK
+ EMPLEADO_ELIMINADO: {
+ codigo: 200,
+ mensaje: 'Empleado(s) eliminado(s) correctamente.',
+ },
+ LISTA_EMPLEADOS_EXPORTADA: {
+ codigo: 200,
+ mensaje: 'Lista de empleados exportada exitosamente.',
+ },
+ // 204 - No hay datos
+ EMPLEADOS_NO_ENCONTRADOS: {
+ codigo: 204,
+ mensaje: 'No hay empleados para exportar.',
+ },
+ // 500 - Internal Server Error
+ ERROR_ELIMINAR_EMPLEADO: {
+ codigo: 500,
+ mensaje: 'Error al eliminar los empleados.',
+ },
+ // 201 - OK
+ GRUPO_CREADO: {
+ codigo: 201,
+ mensaje: 'Grupo de empleados creado correctamente.',
+ },
+
+ // 400 - Bad Request
+ DATOS_INCOMPLETOS: {
+ codigo: 400,
+ mensaje: 'Faltan datos requeridos: nombre del grupo o lista de empleados.',
+ },
+
+ // 500 - Internal Server Error
+ ERROR_CREAR_GRUPO: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al crear el grupo de empleados.',
+ },
+ GRUPO_NOMBRE_REPETIDO: {
+ codigo: 'GRUPO_NOMBRE_REPETIDO',
+ mensaje: 'Ya existe un grupo con ese nombre.',
+ },
+ ERROR_CREACION: {
+ codigo: 500,
+ mensaje: 'Error al crear el empleado',
+ },
+};
diff --git a/Utilidades/Constantes/mensajesEventos.js b/Utilidades/Constantes/mensajesEventos.js
new file mode 100644
index 00000000..78590e3b
--- /dev/null
+++ b/Utilidades/Constantes/mensajesEventos.js
@@ -0,0 +1,98 @@
+module.exports = {
+ // 201 - Creado
+ EVENTO_CREADO: {
+ codigo: 201,
+ mensaje: 'Evento creado correctamente.',
+ },
+
+ // 200 - OK
+ EVENTO_OBTENIDO: {
+ codigo: 200,
+ mensaje: 'Información del evento obtenida exitosamente.',
+ },
+ LISTA_EVENTOS_OBTENIDA: {
+ codigo: 200,
+ mensaje: 'Lista de eventos obtenida exitosamente.',
+ },
+ EVENTO_ELIMINADO: {
+ codigo: 200,
+ mensaje: 'Evento eliminado correctamente.',
+ },
+
+ // 204 - Sin contenido
+ CATEGORIAS_NO_ENCONTRADAS: {
+ codigo: 204,
+ mensaje: 'No se encontraron categorías registradas.',
+ },
+ EVENTOS_NO_ENCONTRADOS: {
+ codigo: 204,
+ mensaje: 'No se encontraron eventos registrados.',
+ },
+
+ // 400 - Bad Request
+ DATOS_INCOMPLETOS: {
+ codigo: 400,
+ mensaje: 'Faltan campos requeridos para crear la categoría.',
+ },
+ NOMBRE_CATEGORIA_INVALIDO: {
+ codigo: 400,
+ mensaje: 'El nombre de la categoría proporcionado no es válido.',
+ },
+ CATEGORIA_YA_EXISTE: {
+ codigo: 400,
+ mensaje: 'Ya existe una categoría con ese nombre.',
+ },
+ PARAMETROS_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Los parámetros proporcionados no son válidos.',
+ },
+ NOMBRE_EVENTO_INVALIDO: {
+ codigo: 400,
+ mensaje: 'El nombre del evento proporcionado no es válido.',
+ },
+ EVENTO_YA_EXISTE: {
+ codigo: 400,
+ mensaje: 'Ya existe un evento con ese nombre.',
+ },
+ // 400 - Error de cliente
+ ERROR_CLIENTE_NO_EXISTE: {
+ codigo: 400,
+ mensaje: 'El cliente especificado no existe en el sistema.',
+ },
+
+ // 404 - No encontrado
+ EVENTO_NO_ENCONTRADO: {
+ codigo: 404,
+ mensaje: 'No se encontró un evento con el ID proporcionado.',
+ },
+
+ // 500 - Error del servidor
+ ERROR_CREAR_EVENTO: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al intentar crear el evento.',
+ },
+ ERROR_OBTENER_EVENTOS: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al obtener la lista de eventos.',
+ },
+ ERROR_OBTENER_EVENTO: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al obtener los datos del evento.',
+ },
+ ERROR_ELIMINAR_EVENTO: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al eliminar el evento.',
+ },
+ ERROR_INTERNO: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error interno en el servidor.',
+ },
+ ERROR_DB_CONEXION: {
+ codigo: 500,
+ mensaje: 'Error de conexión con la base de datos.',
+ },
+ ERROR_INESPERADO: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error inesperado al crear el evento.',
+ },
+};
diff --git a/Utilidades/Constantes/mensajesGrupoEmpleados.js b/Utilidades/Constantes/mensajesGrupoEmpleados.js
new file mode 100644
index 00000000..1e3dd0ef
--- /dev/null
+++ b/Utilidades/Constantes/mensajesGrupoEmpleados.js
@@ -0,0 +1,74 @@
+module.exports = {
+ // 200 - OK
+ CONSULTA_EXITOSA: {
+ codigo: 200,
+ mensaje: 'Lista de grupos de empleados obtenida exitosamente.',
+ },
+
+ GRUPO_OBTENIDO: {
+ codigo: 200,
+ mensaje: 'Información del grupo de empleados obtenida exitosamente.',
+ },
+
+ // 204 - No Content
+ SIN_RESULTADOS: {
+ codigo: 204,
+ mensaje: 'No se encontraron grupos de empleados registrados para el cliente.',
+ },
+
+ // 400 - Bad Request
+ PARAMETROS_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Los parámetros proporcionados no son válidos o están incompletos.',
+ },
+
+ GRUPO_NO_ENCONTRADO: {
+ codigo: 400,
+ mensaje: 'No se encontró un grupo con el ID proporcionado.',
+ },
+
+ // 403 - Forbidden
+ PERMISO_DENEGADO: {
+ codigo: 403,
+ mensaje: 'No tiene permiso para consultar grupos de empleados de este cliente.',
+ },
+
+ // 500 - Internal Server Error
+ ERROR_CONSULTAR_GRUPOS: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al obtener la lista de grupos de empleados.',
+ },
+
+ ELIMINAR_GRUPO_EXITOSO: {
+ codigo: 200,
+ mensaje: 'Grupo de empleados eliminado exitosamente.',
+ },
+ ELIMINAR_GRUPO_ERROR: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al eliminar el grupo de empleados.',
+ },
+ ERROR_OBTENER_GRUPO: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al obtener los datos del grupo de empleados.',
+ },
+ GRUPO_ACTUALIZADO: {
+ codigo: 200,
+ mensaje: 'Se actualizo correctamente el grupo de empleados.',
+ },
+ FORMATO_INVALIDO_DATOS: {
+ codigo: 400,
+ mensaje: 'No se obtuvieron los datos correctamente.',
+ },
+ ERROR_ACTUALIZAR_GRUPOS: {
+ codigo: 400,
+ mensaje: 'Error actualizando el grupo de empleados.s',
+ },
+ ERROR_VERIFICACION_CLIENTE_EMPLEADO: {
+ codigo: 400,
+ mensaje: 'Algunos empleados no pertenecen al mismo cliente que el grupo.',
+ },
+ ERROR_VERIFICACION_CLIENTE_SET: {
+ codigo: 400,
+ mensaje: 'Algunos sets de productos no pertenecen al cliente de este grupo.',
+ },
+};
diff --git a/Utilidades/Constantes/mensajesPagos.js b/Utilidades/Constantes/mensajesPagos.js
new file mode 100644
index 00000000..f821cd64
--- /dev/null
+++ b/Utilidades/Constantes/mensajesPagos.js
@@ -0,0 +1,22 @@
+module.exports = {
+ CONSULTA_EXITOSA: {
+ codigo: 200,
+ mensaje: 'Consulta de tipos de pago exitosa',
+ },
+ ERROR_CONSULTA: {
+ codigo: 400,
+ mensaje: 'Error al consultar pagos',
+ },
+ ERROR_CLIENTE_SELECCIONADO: {
+ codigo: 400,
+ mensaje: 'No se ha seleccionado un cliente',
+ },
+ EXITO_ACTUALIZAR: {
+ codigo: 200,
+ mensaje: 'Actualizacion exitosa',
+ },
+ ERROR_ACTUALIZAR: {
+ codigo: 400,
+ mensaje: 'Error al actualizar',
+ },
+};
diff --git a/Utilidades/Constantes/mensajesPedidos.js b/Utilidades/Constantes/mensajesPedidos.js
new file mode 100644
index 00000000..978727e6
--- /dev/null
+++ b/Utilidades/Constantes/mensajesPedidos.js
@@ -0,0 +1,44 @@
+module.exports = {
+ // 204 - Sin contenido
+ SIN_RESULTADOS: {
+ codigo: 204,
+ mensaje: 'No se encontraron pedidos.',
+ },
+ // 200 - OK
+ CONSULTA_EXITOSA: {
+ codigo: 200,
+ mensaje: 'Lista de pedidos obtenida exitosamente.',
+ },
+ PEDIDO_ELIMINADO: {
+ codigo: 200,
+ mensaje: 'Pedido eliminado correctamente.',
+ },
+ // 403 - Acceso denegado
+ PERMISO_DENEGADO: {
+ codigo: 403,
+ mensaje: 'No tiene permiso para consultar pedidos de este cliente.',
+ },
+ // 404 - No encontrado
+ PEDIDO_NO_ENCONTRADO: {
+ codigo: 404,
+ mensaje: 'No se encontró el pedido solicitado.',
+ },
+ // 500 - Error del servidor
+ ERROR_CONSULTAR_PEDIDOS: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al obtener la lista de pedidos.',
+ },
+ ERROR_ELIMINAR_PEDIDO: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al eliminar el pedido.',
+ },
+ PEDIDO_ACTUALIZADO: {
+ codigo: 200,
+ mensaje: 'Pedido actualizado correctamente.',
+ },
+ ERROR_ACTUALIZAR_PEDIDO: {
+ codigo: 400,
+ mensaje: 'Error al actualizar el pedido.',
+ },
+
+};
diff --git a/Utilidades/Constantes/mensajesProductos.js b/Utilidades/Constantes/mensajesProductos.js
new file mode 100644
index 00000000..7f713977
--- /dev/null
+++ b/Utilidades/Constantes/mensajesProductos.js
@@ -0,0 +1,103 @@
+module.exports = {
+ // 200 - OK
+ CONSULTA_EXITOSA: {
+ codigo: 200,
+ mensaje: 'Lista de productos obtenida exitosamente.',
+ },
+ PRODUCTO_CREADO_EXITOSAMENTE: {
+ codigo: 200,
+ mensaje: 'Producto creado correctamente.',
+ },
+
+ // 204 - No Content
+ SIN_RESULTADOS: {
+ codigo: 204,
+ mensaje: 'No se encontraron productos registrados para el cliente.',
+ },
+ PRODUCTOS_NO_ENCONTRADOS: {
+ codigo: 204,
+ mensaje: 'No se encontraron productos para exportar.',
+ },
+
+ // 400 - Bad Request
+ PARAMETROS_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Los parámetros proporcionados no son válidos o están incompletos.',
+ },
+ LIMITE_OFFSET_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Los valores de límite u offset deben ser números positivos.',
+ },
+
+ // 403 - Forbidden
+ PERMISO_DENEGADO: {
+ codigo: 403,
+ mensaje: 'No tiene permiso para consultar productos de este cliente.',
+ },
+
+ // 500 - Internal Server Error
+ ERROR_CONSULTAR_PRODUCTOS: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al obtener la lista de productos.',
+ },
+ ERROR_CREAR_PRODUCTO: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al crear el producto. Por favor, intente nuevamente más tarde.',
+ },
+ ERROR_ENVIAR_IMAGENES_S3: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al subir las imágenes al servidor. Intente nuevamente.',
+ },
+ ERROR_CREAR_VARIANTE: {
+ codigo: 500,
+ mensaje:
+ 'Ocurrió un error al crear una variante del producto. Verifique los datos de variantes.',
+ },
+ ERROR_CREAR_OPCION: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al crear una opción para la variante. Revise las opciones enviadas.',
+ },
+
+ ERROR_CREAR_IMAGEN_VARIANTE: {
+ codigo: 500,
+ mensaje:
+ 'Ocurrió un error al asociar la imagen con la variante. Verifique los datos de las imágenes de variantes.',
+ },
+
+ // 200 - OK
+ RESPUESTA_ELIMINAR_PRODUCTO_EXITOSA: {
+ codigo: 200,
+ mensaje: 'Producto eliminado exitosamente.',
+ },
+
+ // 500 - Internal Server Error
+ RESPUESTA_ERROR_GENERAL: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al procesar la solicitud.',
+ },
+ //LEER PRODUCTO
+ ERROR_LEER_PRODUCTO: {
+ codigo: 400,
+ mensaje: 'Ocurrió un error al obtener la informacion del producto.',
+ },
+ LEER_PRODUCTO_EXITO: {
+ codigo: 200,
+ mensaje: 'Lista de productos consultada exitosamente.',
+ },
+ ID_INVALIDO: {
+ codigo: 400,
+ mensaje: 'No se proporciono el id del producto.',
+ },
+ ERROR_OBTENIENDO_INFORMACION: {
+ codigo: 400,
+ mensaje: 'Error obteniendo informacion del producto.',
+ },
+ PRODUCTO_NO_ENCONTRADO: {
+ codigo: 400,
+ mensaje: 'El producto solicitado no existe.',
+ },
+ ERROR_EXPORTACION: {
+ codigo: 400,
+ mensaje: 'Error al exportar la lista de productos.',
+ },
+};
diff --git a/Utilidades/Constantes/mensajesProveedores.js b/Utilidades/Constantes/mensajesProveedores.js
new file mode 100644
index 00000000..20d8f3fa
--- /dev/null
+++ b/Utilidades/Constantes/mensajesProveedores.js
@@ -0,0 +1,53 @@
+module.exports = {
+ // 200 - OK
+ PROVEEDOR_CREADO_EXITOSAMENTE: {
+ codigo: 200,
+ mensaje: 'El proveedor fue creado exitosamente.',
+ },
+ CONSULTA_PROVEEDORES_EXITOSA: {
+ codigo: 200,
+ mensaje: 'Lista de proveedores obtenida exitosamente.',
+ },
+ PROVEEDOR_OBTENIDO_EXITOSAMENTE: {
+ codigo: 200,
+ mensaje: 'Información del proveedor obtenida exitosamente.',
+ },
+
+ // 204 - No Content
+ LISTA_PROVEEDORES_VACIA: {
+ codigo: 204,
+ mensaje: 'No hay proveedores registrados actualmente.',
+ },
+
+ // 400 - Bad Request
+ DATOS_PROVEEDOR_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Los datos del proveedor proporcionados son inválidos o están incompletos.',
+ },
+
+ // 403 - Forbidden
+ ACCESO_NO_AUTORIZADO_PROVEEDORES: {
+ codigo: 403,
+ mensaje: 'No tiene permiso para consultar o modificar proveedores.',
+ },
+
+ // 404 - Not Found
+ PROVEEDOR_NO_ENCONTRADO: {
+ codigo: 404,
+ mensaje: 'No se encontró un proveedor con el ID proporcionado.',
+ },
+
+ // 500 - Internal Server Error
+ ERROR_CREAR_PROVEEDOR: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al intentar crear el proveedor.',
+ },
+ ERROR_CONSULTAR_PROVEEDORES: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al obtener la lista de proveedores.',
+ },
+ ERROR_CONSULTAR_PROVEEDOR: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al obtener la información del proveedor.',
+ },
+};
diff --git a/Utilidades/Constantes/mensajesRoles.js b/Utilidades/Constantes/mensajesRoles.js
new file mode 100644
index 00000000..d8ab3f05
--- /dev/null
+++ b/Utilidades/Constantes/mensajesRoles.js
@@ -0,0 +1,97 @@
+/**
+ * @file mensajesRoles.js
+ * @description
+ * Contiene las constantes de mensajes utilizadas para las respuestas HTTP
+ * relacionadas con la entidad "Rol" en el backend.
+ * Cada constante define un código de estado HTTP y un mensaje descriptivo,
+ * lo cual facilita respuestas consistentes y claras desde los controladores.
+ *
+ * @exports CONSULTA_EXITOSA, SIN_RESULTADOS, PARAMETROS_INVALIDOS,
+ * LIMITE_OFFSET_INVALIDOS, ERROR_CONSULTAR_ROLES
+ */
+
+module.exports = {
+ /**
+ * Mensaje utilizado cuando la consulta de roles se realiza con éxito.
+ *
+ * @constant
+ * @type {{codigo: number, mensaje: string}}
+ */
+ CONSULTA_EXITOSA: {
+ codigo: 200,
+ mensaje: 'Lista de roles obtenida exitosamente.',
+ },
+
+ /**
+ * Mensaje utilizado cuando la consulta no devuelve ningún resultado.
+ *
+ * @constant
+ * @type {{codigo: number, mensaje: string}}
+ */
+ SIN_RESULTADOS: {
+ codigo: 204,
+ mensaje: 'No se encontraron roles registrados para el cliente.',
+ },
+
+ /**
+ * Mensaje utilizado cuando los parámetros de entrada son inválidos o faltan.
+ *
+ * @constant
+ * @type {{codigo: number, mensaje: string}}
+ */
+ PARAMETROS_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Los parámetros proporcionados no son válidos o están incompletos.',
+ },
+
+ /**
+ * Mensaje específico para errores relacionados con paginación.
+ * Generalmente usado si el límite o el desplazamiento (offset) son inválidos.
+ *
+ * @constant
+ * @type {{codigo: number, mensaje: string}}
+ */
+ LIMITE_OFFSET_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Los valores de límite u offset deben ser números positivos.',
+ },
+
+ /**
+ * Mensaje de error general utilizado cuando ocurre un fallo inesperado
+ * durante la consulta de roles en el backend.
+ *
+ * @constant
+ * @type {{codigo: number, mensaje: string}}
+ */
+ ERROR_CONSULTAR_ROLES: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al obtener la lista de roles.',
+ },
+
+ ELIMINAR_ROL_EXITO: {
+ codigo: 200,
+ mensaje: 'Se elimino el rol correctamente',
+ },
+ ELIMINAR_ROL_ERROR: {
+ codigo: 400,
+ mensaje: 'Ocurrió un error al eliminar rol',
+ mensaje_no_existe: 'Ocurrió un error, rol no existe',
+ mensaje_rol_asignado: 'No se puede eliminar el rol porque está asignado a uno o más usuarios.',
+
+ },
+ ACTUALIZAR_ROL: {
+ codigo: 200,
+ mensaje: 'Se actualizo correctamente el rol.',
+ },
+
+ NOMBRE_OBLIGATORIO: 'El nombre del rol es obligatorio.',
+ PERMISOS_OBLIGATORIOS: 'Debes seleccionar al menos un permiso.',
+ ROL_EXISTENTE: 'Ya existe un rol con ese nombre.',
+ ROL_CREADO: 'Rol creado exitosamente.',
+ ERROR_CREACION: 'Error al crear el rol.',
+ PERMISO_INVALIDO: (id) => `El permiso con ID "${id}" no existe.`,
+ FALTA_ID_CLIENTE: 'Falta el ID del cliente',
+ OPCIONES_OBTENIDAS: 'Permisos obtenidos correctamente',
+ ERROR_OBTENIENDO_OPCIONES: 'Error al obtener permisos',
+ ERROR_OBTENIENDO_PERMISOS: 'Error al obtener la lista de permisos.',
+};
diff --git a/Utilidades/Constantes/mensajesSetsProductos.js b/Utilidades/Constantes/mensajesSetsProductos.js
new file mode 100644
index 00000000..3d8291c9
--- /dev/null
+++ b/Utilidades/Constantes/mensajesSetsProductos.js
@@ -0,0 +1,95 @@
+module.exports = {
+ // 200 - OK
+ CONSULTA_EXITOSA: {
+ codigo: 200,
+ mensaje: 'Lista de sets de productos obtenida exitosamente.',
+ },
+ SET_PRODUCTOS_ELIMINADO: {
+ codigo: 200,
+ mensaje: 'Set de productos eliminado correctamente.',
+ },
+ SET_PRODUCTOS_ACTUALIZADO: {
+ codigo: 200,
+ mensaje: 'Set de productos actualizado correctamente.',
+ },
+
+ // 204 - No Content
+ SIN_RESULTADOS: {
+ codigo: 204,
+ mensaje: 'No se encontraron sets de productos registrados para el cliente.',
+ },
+
+ // 403 - Forbidden
+ PERMISO_DENEGADO: {
+ codigo: 403,
+ mensaje: 'No tiene permiso para consultar sets de productos de este cliente.',
+ },
+
+ // 404 - No encontrado
+ SET_PRODUCTO_NO_ENCONTRADO: {
+ codigo: 404,
+ mensaje: 'Set de productos no encontrado.',
+ },
+
+ // 500 - Internal Server Error
+ ERROR_CONSULTAR_SETS_PRODUCTOS: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al obtener la lista de sets de productos.',
+ },
+ ERROR_ELIMINAR_SET_PRODUCTOS: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al eliminar el set de productos.',
+ },
+ DATOS_INVALIDOS_ERROR: {
+ codigo: 400,
+ mensaje: 'Formato de datos invalido.',
+ },
+ CLIENTE_NO_SELECCIONADO: {
+ codigo: 400,
+ mensaje: 'Cliente no seleccionado.',
+ },
+ SETS_PRODUCTOS_CREADO_EXITO: {
+ codigo: 200,
+ mensaje: 'Set de producto creado exitosamente.',
+ },
+ ERROR_NOMBRE_DUPLICADO: {
+ codigo: 400,
+ mensaje: 'Nombre o nombre visible duplicado.',
+ },
+ ERROR_NOMBRE_NORMAL_DUPLICADO: {
+ codigo: 400,
+ mensaje: 'Nombre duplicado.',
+ },
+ ERROR_PRODUCTOS_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Uno o más productos no existen en este cliente.',
+ },
+ ERROR_ACTUALIZAR_SET_PRODUCTOS: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al actualizar el set de productos',
+ },
+ FORMATO_INVALIDO_DATOS: {
+ codigo: 400,
+ mensaje: 'Formato de datos inválido para actualizar el set de productos',
+ },
+ SET_ACTUALIZADO: {
+ codigo: 200,
+ mensaje: 'Set de productos actualizado correctamente',
+ },
+ ERROR_ACTUALIZAR_SET: {
+ codigo: 500,
+ mensaje: 'Error interno al actualizar el set de productos',
+ },
+ SET_NO_ENCONTRADO: {
+ codigo: 404,
+ mensaje: 'El set de productos no fue encontrado',
+ },
+ PRODUCTOS_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'La lista de productos contiene elementos inválidos',
+ },
+ PARAMETROS_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Parámetros inválidos',
+ },
+};
diff --git a/Utilidades/Constantes/mensajesUsuarios.js b/Utilidades/Constantes/mensajesUsuarios.js
new file mode 100644
index 00000000..898f47a2
--- /dev/null
+++ b/Utilidades/Constantes/mensajesUsuarios.js
@@ -0,0 +1,90 @@
+module.exports = {
+ // 201 - Creado
+ USUARIO_CREADO: {
+ codigo: 201,
+ mensaje: 'Usuario creado correctamente.',
+ },
+
+ // 200 - OK
+ USUARIO_OBTENIDO: {
+ codigo: 200,
+ mensaje: 'Información del usuario obtenida exitosamente.',
+ },
+ LISTA_USUARIOS_OBTENIDA: {
+ codigo: 200,
+ mensaje: 'Lista de usuarios obtenida exitosamente.',
+ },
+
+ // 204 - Sin contenido
+ USUARIOS_NO_ENCONTRADOS: {
+ codigo: 204,
+ mensaje: 'No se encontraron usuarios registrados.',
+ },
+
+ // 400 - Bad Request
+ DATOS_INCOMPLETOS: {
+ codigo: 400,
+ mensaje: 'Faltan campos requeridos para crear el usuario.',
+ },
+ CORREO_INVALIDO: {
+ codigo: 400,
+ mensaje: 'El correo electrónico proporcionado no es válido.',
+ },
+ CONTRASENA_DEBIL: {
+ codigo: 400,
+ mensaje:
+ 'La contraseña debe tener al menos 8 caracteres y contener al menos un carácter especial.',
+ },
+ TELEFONO_INVALIDO: {
+ codigo: 400,
+ mensaje: 'El número de teléfono debe contener exactamente 10 dígitos.',
+ },
+ ROL_O_CLIENTE_INVALIDO: {
+ codigo: 400,
+ mensaje: 'El rol o el cliente especificado no es válido.',
+ },
+ USUARIO_YA_EXISTE: {
+ codigo: 400,
+ mensaje: 'Ya existe un usuario con este correo electrónico.',
+ },
+ PARAMETROS_INVALIDOS: {
+ codigo: 400,
+ mensaje: 'Los parámetros proporcionados no son válidos.',
+ },
+ ERROR_OBTENER_USUARIO: {
+ codigo: 400,
+ mensaje: 'Ocurrió un error al obtener los datos del usuario.',
+ },
+
+ // 401 - sin autorizacion
+ CREDENCIALES_INVALIDAS: {
+ codigo: 401,
+ mensaje: 'Correo electrónico o contraseña incorrectos.',
+ },
+
+ // 403 - Denegado
+ ACCESO_DENEGADO: {
+ codigo: 403,
+ mensaje: 'No tiene permiso para realizar esta acción sobre usuarios.',
+ },
+
+ // 404 - No encontrado
+ USUARIO_NO_ENCONTRADO: {
+ codigo: 404,
+ mensaje: 'No se encontró un usuario con el ID proporcionado.',
+ },
+
+ // 500 - Server Error
+ ERROR_CREAR_USUARIO: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al intentar crear el usuario. Probablemente ya existe.',
+ },
+ ERROR_OBTENER_USUARIOS: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al obtener la lista de usuarios.',
+ },
+ ERROR_ELIMINAR_USUARIO: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error al intentar eliminar el usuario.',
+ },
+};
diff --git a/Utilidades/Constantes/permisos.js b/Utilidades/Constantes/permisos.js
new file mode 100644
index 00000000..417fa8d1
--- /dev/null
+++ b/Utilidades/Constantes/permisos.js
@@ -0,0 +1,120 @@
+module.exports = {
+ // Sistema
+ CONSULTAR_SISTEMA_ADMINISTRATIVO: 'Consultar Sistema Administrativo',
+ CONSULTAR_TIENDA: 'Consultar Tienda',
+
+ // Usuario
+ CREAR_USUARIO: 'Crear Usuario',
+ CONSULTAR_USUARIOS: 'Consultar Lista de Usuarios',
+ LEER_USUARIO: 'Leer Usuario',
+ ACTUALIZAR_USUARIO: 'Actualizar Usuario',
+ ELIMINAR_USUARIOS: 'Eliminar Usuario',
+ ACTIVAR_2FA_SUPERADMIN: 'Activar 2FA para Superadmin',
+ VERIFICAR_2FA_SUPERADMIN: 'Verificar 2FA para Superadmin',
+
+ // Rol
+ CREAR_ROL: 'Crear Rol',
+ CONSULTAR_ROLES: 'Consultar Lista de Roles',
+ LEER_ROL: 'Leer Rol',
+ ACTUALIZAR_ROL: 'Actualizar Rol',
+ ELIMINAR_ROL: 'Eliminar Rol',
+
+ // Cliente
+ CREAR_CLIENTE: 'Crear Cliente',
+ CONSULTAR_CLIENTES: 'Consultar Lista de Clientes',
+ LEER_CLIENTE: 'Leer Cliente',
+ ACTUALIZAR_CLIENTE: 'Actualizar Cliente',
+ ELIMINAR_CLIENTE: 'Eliminar Cliente',
+
+ // Empleado
+ CREAR_EMPLEADO: 'Crear Empleado',
+ CONSULTAR_EMPLEADOS: 'Consultar Lista de Empleados',
+ LEER_EMPLEADO: 'Leer Empleado',
+ ACTUALIZAR_EMPLEADO: 'Actualizar Empleado',
+ ELIMINAR_EMPLEADO: 'Eliminar Empleado',
+
+ // Grupo de Empleados
+ CREAR_GRUPO_EMPLEADOS: 'Crear Grupo de Empleados',
+ CONSULTAR_GRUPOS_EMPLEADOS: 'Consultar Lista de Grupos de Empleados',
+ LEER_GRUPO_EMPLEADOS: 'Leer Grupo de Empleados',
+ ACTUALIZAR_GRUPO_EMPLEADOS: 'Actualizar Grupo de Empleados',
+ ELIMINAR_GRUPO_EMPLEADOS: 'Eliminar Grupo de Empleados',
+
+ // Producto
+ CREAR_PRODUCTO: 'Crear Producto',
+ CONSULTAR_PRODUCTOS: 'Consultar Lista de Productos',
+ LEER_PRODUCTO: 'Leer Producto',
+ ACTUALIZAR_PRODUCTO: 'Actualizar Producto',
+ ELIMINAR_PRODUCTO: 'Eliminar Producto',
+
+ // Set de Cuotas
+ CREAR_SET_CUOTAS: 'Crear Set de Cuotas',
+ CONSULTAR_SETS_CUOTAS: 'Consultar Lista de Sets de Cuotas',
+ LEER_SET_CUOTAS: 'Leer Set de Cuotas',
+ ACTUALIZAR_SET_CUOTAS: 'Actualizar Set de Cuotas',
+ ELIMINAR_SET_CUOTAS: 'Eliminar Set de Cuotas',
+
+ // Evento
+ CREAR_EVENTO: 'Crear Evento',
+ CONSULTAR_EVENTO: 'Consultar Lista de Eventos',
+ LEER_EVENTO: 'Leer Evento',
+ ACTUALIZAR_EVENTO: 'Actualizar Evento',
+ ELIMINAR_EVENTO: 'Eliminar Evento',
+
+ // Set de Productos
+ CREAR_SET_PRODUCTOS: 'Crear Set de Productos',
+ CONSULTAR_SETS_PRODUCTOS: 'Consultar Lista de Sets de Productos',
+ LEER_SET_PRODUCTOS: 'Leer Set de Productos',
+ ACTUALIZAR_SET_PRODUCTOS: 'Actualizar Set de Productos',
+ ELIMINAR_SET_PRODUCTOS: 'Eliminar Set de Productos',
+
+ // Categoría de Productos
+ CREAR_CATEGORIA_PRODUCTOS: 'Crear Categoría de Productos',
+ CONSULTAR_CATEGORIAS_PRODUCTOS: 'Consultar Lista de Categorías de Productos',
+ LEER_CATEGORIA_PRODUCTOS: 'Leer Categoría de Productos',
+ ACTUALIZAR_CATEGORIA_PRODUCTOS: 'Actualizar Categoría de Productos',
+ ELIMINAR_CATEGORIA_PRODUCTOS: 'Eliminar Categoría de Productos',
+
+ // Tipo de Pago
+ CREAR_TIPO_PAGO: 'Crear Tipo de Pago',
+ CONSULTAR_TIPOS_PAGO: 'Consultar Lista de Tipos de Pago',
+ LEER_TIPO_PAGO: 'Leer Tipo de Pago',
+ ACTUALIZAR_TIPO_PAGO: 'Actualizar Tipo de Pago',
+ ELIMINAR_TIPO_PAGO: 'Eliminar Tipo de Pago',
+
+ // Importar / Exportar
+ IMPORTAR_PRODUCTOS: 'Importar Productos',
+ IMPORTAR_EMPLEADOS: 'Importar Empleados',
+ EXPORTAR_PRODUCTOS: 'Exportar Productos',
+ EXPORTAR_EMPLEADOS: 'Exportar Empleados',
+
+ // Pedido
+ CONSULTAR_PEDIDOS: 'Consultar Lista de Pedidos',
+ LEER_PEDIDO: 'Leer Pedido',
+ ACTUALIZAR_PEDIDO: 'Actualizar Pedido',
+ ELIMINAR_PEDIDO: 'Eliminar Pedido',
+
+ // Ayuda
+ ACCEDER_CENTRO_AYUDA: 'Acceder al Centro de Ayuda',
+
+ // Carrito
+ LEER_CARRITO: 'Leer Carrito de Compras',
+ ACTUALIZAR_CARRITO: 'Actualizar Carrito de Compras',
+ ELIMINAR_PRODUCTO_CARRITO: 'Eliminar Productos del Carrito',
+ AGREGAR_PRODUCTO_CARRITO: 'Agregar Producto al Carrito',
+
+ // Pedido Tienda
+ CREAR_PEDIDO: 'Crear Pedido',
+ LEER_PEDIDO_TIENDA: 'Leer Pedido Tienda',
+ FINALIZAR_PEDIDO: 'Finalizar Pedido',
+ CONSULTAR_PEDIDOS_TIENDA: 'Consultar Lista de Pedidos Tienda',
+ RECIBIR_NOTIFICACIONES_PEDIDO: 'Recibir Notificaciones de Estado del Pedido',
+
+ // Producto Tienda
+ LEER_PRODUCTO_TIENDA: 'Leer Producto Tienda',
+ CONSULTAR_PRODUCTOS_TIENDA: 'Consultar Lista de Productos Tienda',
+
+ // Balance / Pago
+ LEER_BALANCE: 'Leer Balance',
+ SELECCIONAR_TIPO_PAGO: 'Seleccionar Tipo de Pago',
+};
diff --git a/Utilidades/Constantes/rutas.js b/Utilidades/Constantes/rutas.js
new file mode 100644
index 00000000..c9ba52b7
--- /dev/null
+++ b/Utilidades/Constantes/rutas.js
@@ -0,0 +1,115 @@
+module.exports = {
+ RAIZ: '/',
+ API: '/api',
+ AUTENTICACION: {
+ BASE: '/autenticacion',
+ INICIO_SESION: '/iniciar-sesion',
+ REGISTRO: '/registro',
+ CERRAR_SESION: '/cerrar-sesion',
+ USUARIO_AUTENTICADO: '/autenticar',
+ ACTIVAR_2FA: '/activar-2fa',
+ VERIFICAR_2FA: '/verificar-2fa',
+ },
+ USUARIOS: {
+ BASE: '/usuarios',
+ CONSULTAR_LISTA_USUARIOS: '/consultar-lista-usuarios',
+ CREAR: '/crear',
+ ELIMINAR_USUARIOS: '/eliminar-usuarios',
+ LEER: '/consultar-usuario',
+ },
+ CATEGORIAS: {
+ BASE: '/categorias',
+ CONSULTAR_LISTA_CATEGORIAS: '/consultar-lista-categorias',
+ CREAR_CATEGORIA: '/crear-categoria',
+ ELIMINAR_CATEGORIA: '/eliminar',
+ CONSULTAR_LISTA_USUARIOS: '/consultar-lista-usuarios',
+ CREAR: '/crear',
+ ELIMINAR_USUARIOS: '/eliminar-usuarios',
+ LEER: '/leer',
+ ACTUALIZAR: '/actualizar',
+ },
+ EVENTOS: {
+ BASE: '/eventos',
+ CREAR: '/crear',
+ ELIMINAR: '/eliminar',
+ EDITAR: '/editar',
+ CONSULTAR_LISTA_EVENTOS: '/consultar-lista-eventos',
+ CONSULTAR_EVENTO: '/consultar-evento',
+ },
+ PRODUCTOS: {
+ BASE: '/productos',
+ CONSULTAR_LISTA: '/consultar-lista',
+ CREAR: '/crear',
+ ELIMINAR_PRODUCTO: '/eliminar',
+ IMPORTAR: '/importar',
+ LEER: '/leer-producto',
+ EXPORTAR_PRODUCTOS: '/exportar-productos',
+ },
+ PROVEEDORES: {
+ BASE: '/proveedores',
+ CONSULTAR_LISTA: '/consultar-lista',
+ CREAR: '/crear',
+ },
+ SETS_PRODUCTOS: {
+ BASE: '/sets-productos',
+ CONSULTAR_LISTA: '/consultar-lista',
+ CREAR: '/crear',
+ SUBIR_IMAGEN: '/subir-imagen',
+ ELIMINAR_SET_PRODUCTOS: '/eliminar',
+ ACTUALIZAR: '/actualizar',
+ },
+ CLIENTES: {
+ BASE: '/clientes',
+ CONSULTAR_SISTEMA: '/consultar-sistema',
+ CONSULTAR_LISTA: '/consultar-lista',
+ ELIMINAR_CLIENTE: '/eliminar',
+ CREAR_CLIENTE: '/crear-cliente',
+ LEER: '/consultar-cliente',
+ ACTUALIZAR: `/actualizar-cliente`,
+ },
+ EMPLEADOS: {
+ BASE: '/empleados',
+ CREAR: '/crear',
+ CONSULTAR_LISTA: '/consultar-lista',
+ CONSULTAR_GRUPO: '/consultar-grupo',
+ ELIMINAR_GRUPO: '/eliminar-grupo',
+ ELIMINAR_EMPLEADO: '/eliminar',
+ IMPORTAR_EMPLEADOS: '/importar-empleados',
+ EXPORTAR_EMPLEADOS: '/exportar-empleados',
+ LEER_GRUPO: '/leer-grupo',
+ CREAR_GRUPO: '/crear-grupo',
+ ACTUALIZAR: '/actualizar',
+ ACTUALIZAR_GRUPO_EMPLEADO: '/actualizar-grupo',
+ },
+ CUOTAS: {
+ BASE: '/cuotas',
+ AGREGAR: '/crear-cuota',
+ OPCIONES: '/obtener-opciones',
+ CONSULTAR_LISTA: '/consultar-lista',
+ ELIMINAR_SET_CUOTAS: '/eliminar-set-cuotas',
+ LEER_SET_CUOTAS: '/leer-set-cuotas',
+ ACTUALIZAR_SET_CUOTAS: '/actualizar-set-cuotas',
+ },
+ ROLES: {
+ BASE: '/roles',
+ CONSULTAR_LISTA: '/consultar-lista',
+ CREAR_ROL: '/crear-rol',
+ OBTENER_OPCIONES: '/obtener-opciones',
+ CONFIRMAR_CREACION: '/confirmar-creacion',
+ ELIMINAR_ROL: '/eliminar',
+ LEER_ROL: '/leer',
+ ACTUALIZAR: '/actualizar-rol',
+ },
+ PEDIDOS: {
+ BASE: '/pedidos',
+ CONSULTAR_LISTA: '/consultar-lista',
+ ELIMINAR_PEDIDO: '/eliminar',
+ ACTUALIZAR_PEDIDO: '/actualizar-pedido',
+ },
+ PAGOS: {
+ BASE: '/pagos',
+ CONSULTAR_LISTA: '/consultar-lista',
+ ACTUALIZAR: '/actualizar',
+ },
+ API_DOCS: '/api-docs',
+};
diff --git a/Utilidades/Intermediarios/Validaciones/validarOpciones.js b/Utilidades/Intermediarios/Validaciones/validarOpciones.js
new file mode 100644
index 00000000..8dc60a95
--- /dev/null
+++ b/Utilidades/Intermediarios/Validaciones/validarOpciones.js
@@ -0,0 +1,86 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+/**
+ * Valida un conjunto de opciones para un producto.
+ *
+ * Esta función valida cada opción dentro del arreglo de opciones pasado como argumento.
+ * Se asegura de que los valores de las propiedades cumplan con los tipos y rangos especificados,
+ * y retorna un objeto de error si algún valor es inválido.
+ *
+ * @param {Array} opciones - Un arreglo de objetos que representan las opciones de un producto.
+ * @param {number} opciones[].cantidad - La cantidad de la opción, que debe ser un número entero positivo o cero.
+ * @param {string} opciones[].valorOpcion - El valor de la opción, que debe ser una cadena de texto de máximo 100 caracteres.
+ * @param {string} [opciones[].SKUautomatico] - El SKU automático de la opción, que debe ser una cadena de texto de máximo 50 caracteres, si se proporciona.
+ * @param {string} [opciones[].SKUcomercial] - El SKU comercial de la opción, que debe ser una cadena de texto de máximo 50 caracteres, si se proporciona.
+ * @param {number} opciones[].costoAdicional - El costo adicional de la opción, que debe ser un número positivo o cero.
+ * @param {number} opciones[].descuento - El descuento de la opción, que debe ser un número entre 0 y 100.
+ * @param {number} opciones[].estado - El estado de la opción, que debe ser 1 (activo) o 0 (inactivo).
+ *
+ * @returns {object|null} Un objeto con una propiedad `error` si hay un error de validación, o `null` si todas las opciones son válidas.
+ * @example
+ * const opciones = [
+ * {
+ * cantidad: 5,
+ * valorOpcion: 'Tamaño M',
+ * SKUautomatico: 'SKU123',
+ * SKUcomercial: 'S123',
+ * costoAdicional: 15.50,
+ * descuento: 10,
+ * estado: 1
+ * }
+ * ];
+ *
+ * const resultado = validarOpciones(opciones);
+ * console.log(resultado); // null si todo está bien, o un objeto de error si algo es inválido
+ */
+module.exports = (opciones) => {
+ for (const opcion of opciones) {
+ // prettier-ignore
+ if (
+ typeof opcion.cantidad !== 'number'
+ || opcion.cantidad < 0
+ || !Number.isInteger(opcion.cantidad)
+ ) {
+ return { error: 'cantidad de la opción debe ser un número entero positivo o cero.' };
+ }
+
+ // prettier-ignore
+ if (
+ !opcion.valorOpcion
+ || typeof opcion.valorOpcion !== 'string'
+ || opcion.valorOpcion.length > 100
+ ) {
+ return {
+ error: 'valorOpcion es requerido y debe ser una cadena de texto de máximo 100 caracteres.',
+ };
+ }
+
+ // prettier-ignore
+ if (
+ opcion.SKUautomatico
+ && (typeof opcion.SKUautomatico !== 'string' || opcion.SKUautomatico.length > 50)
+ ) {
+ return { error: 'SKUautomatico debe ser una cadena de texto de máximo 50 caracteres.' };
+ }
+ // prettier-ignore
+ if (
+ opcion.SKUcomercial
+ && (typeof opcion.SKUcomercial !== 'string' || opcion.SKUcomercial.length > 50)
+ ) {
+ return { error: 'SKUcomercial debe ser una cadena de texto de máximo 50 caracteres.' };
+ }
+
+ if (typeof opcion.costoAdicional !== 'number' || opcion.costoAdicional < 0) {
+ return { error: 'costoAdicional debe ser un número positivo o cero.' };
+ }
+
+ if (typeof opcion.descuento !== 'number' || opcion.descuento < 0 || opcion.descuento > 100) {
+ return { error: 'descuento debe ser un número entre 0 y 100.' };
+ }
+
+ if (typeof opcion.estado !== 'number' || (opcion.estado !== 0 && opcion.estado !== 1)) {
+ return { error: 'estado debe ser 1 (activo) o 0 (inactivo).' };
+ }
+ }
+
+ return null;
+};
diff --git a/Utilidades/Intermediarios/Validaciones/validarOpcionesImportar.js b/Utilidades/Intermediarios/Validaciones/validarOpcionesImportar.js
new file mode 100644
index 00000000..69e7775e
--- /dev/null
+++ b/Utilidades/Intermediarios/Validaciones/validarOpcionesImportar.js
@@ -0,0 +1,81 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+/**
+ * Valida un conjunto de opciones para un producto.
+ *
+ * Esta función valida cada opción dentro del arreglo de opciones pasado como argumento.
+ * Se asegura de que los valores de las propiedades cumplan con los tipos y rangos especificados,
+ * y retorna un objeto de error si algún valor es inválido.
+ *
+ * @param {Array} opciones - Un arreglo de objetos que representan las opciones de un producto.
+ * @param {number} opciones[].cantidad - La cantidad de la opción, que debe ser un número entero positivo o cero.
+ * @param {string} opciones[].valorOpcion - El valor de la opción, que debe ser una cadena de texto de máximo 100 caracteres.
+ * @param {string} [opciones[].SKUautomatico] - El SKU automático de la opción, que debe ser una cadena de texto de máximo 50 caracteres, si se proporciona.
+ * @param {string} [opciones[].SKUcomercial] - El SKU comercial de la opción, que debe ser una cadena de texto de máximo 50 caracteres, si se proporciona.
+ * @param {number} opciones[].costoAdicional - El costo adicional de la opción, que debe ser un número positivo o cero.
+ * @param {number} opciones[].descuento - El descuento de la opción, que debe ser un número entre 0 y 100.
+ * @param {number} opciones[].estado - El estado de la opción, que debe ser 1 (activo) o 0 (inactivo).
+ *
+ * @returns {object|null} Un objeto con una propiedad `error` si hay un error de validación, o `null` si todas las opciones son válidas.
+ * @example
+ * const opciones = [
+ * {
+ * cantidad: 5,
+ * valorOpcion: 'Tamaño M',
+ * SKUautomatico: 'SKU123',
+ * SKUcomercial: 'S123',
+ * costoAdicional: 15.50,
+ * descuento: 10,
+ * estado: 1
+ * }
+ * ];
+ *
+ * const resultado = validarOpciones(opciones);
+ * console.log(resultado); // null si todo está bien, o un objeto de error si algo es inválido
+ */
+module.exports = (opciones) => {
+ for (const opcion of opciones) {
+ // prettier-ignore
+ if (
+ typeof opcion.cantidad !== 'number'
+ || opcion.cantidad < 0
+ || !Number.isInteger(opcion.cantidad)
+ || opcion.cantidad % 1 !== 0
+ ) {
+ return { error: 'cantidad de la opción debe ser un número entero positivo o cero.' };
+ }
+
+ // prettier-ignore
+ if (
+ !opcion.valorOpcion
+ || typeof opcion.valorOpcion !== 'string'
+ || opcion.valorOpcion.length > 100
+ ) {
+ return {
+ error: 'valorOpcion es requerido y debe ser una cadena de texto de máximo 100 caracteres.',
+ };
+ }
+
+ // prettier-ignore
+ if (!opcion.SKUcomercial
+ || opcion.SKUcomercial == null
+ || typeof opcion.SKUcomercial !== 'string'
+ || opcion.SKUcomercial.length > 50
+ ) {
+ return { error: 'SKUcomercial debe ser una cadena de texto de máximo 50 caracteres.' };
+ }
+
+ if (typeof opcion.costoAdicional !== 'number' || opcion.costoAdicional < 0) {
+ return { error: 'costoAdicional debe ser un número positivo o cero.' };
+ }
+
+ if (typeof opcion.descuento !== 'number' || opcion.descuento < 0 || opcion.descuento > 100) {
+ return { error: 'descuento debe ser un número entre 0 y 100.' };
+ }
+
+ if (typeof opcion.estado !== 'number' || (opcion.estado !== 0 && opcion.estado !== 1)) {
+ return { error: 'estado debe ser 1 (activo) o 0 (inactivo).' };
+ }
+ }
+
+ return null;
+};
diff --git a/Utilidades/Intermediarios/Validaciones/validarProducto.js b/Utilidades/Intermediarios/Validaciones/validarProducto.js
new file mode 100644
index 00000000..5738d072
--- /dev/null
+++ b/Utilidades/Intermediarios/Validaciones/validarProducto.js
@@ -0,0 +1,138 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+/**
+ * Valida los campos de un producto.
+ *
+ * Esta función valida los diferentes campos de un objeto `producto` asegurándose de que cumplan con los tipos y restricciones especificados. Si algún campo no cumple con las condiciones, se devuelve un objeto de error con un mensaje específico. Si todos los campos son válidos, se retorna `null`.
+ *
+ * @param {object} producto - El objeto que representa un producto a validar.
+ * @param {number|null} producto.idProveedor - El ID del proveedor, debe ser un número entero positivo o `null`.
+ * @param {string} producto.nombreComun - El nombre común del producto, debe ser una cadena de texto de máximo 100 caracteres.
+ * @param {string|null} producto.nombreComercial - El nombre comercial del producto, debe ser una cadena de texto de máximo 150 caracteres o `null`.
+ * @param {string|null} producto.descripcion - Descripción del producto, debe ser una cadena de texto de máximo 1000 caracteres o `null`.
+ * @param {string|null} producto.marca - La marca del producto, debe ser una cadena de texto de máximo 100 caracteres o `null`.
+ * @param {string|null} producto.modelo - El modelo del producto, debe ser una cadena de texto de máximo 100 caracteres o `null`.
+ * @param {string|null} producto.tipoProducto - El tipo de producto, debe ser una cadena de texto de máximo 50 caracteres o `null`.
+ * @param {number|null} producto.precioPuntos - El precio en puntos, debe ser un número entero positivo o `null`.
+ * @param {number|null} producto.precioCliente - El precio para el cliente, debe ser un número mayor o igual a cero o `null`.
+ * @param {number|null} producto.precioVenta - El precio de venta, debe ser un número mayor o igual a cero o `null`.
+ * @param {number|null} producto.costo - El costo del producto, debe ser un número mayor o igual a cero o `null`.
+ * @param {number|null} producto.impuesto - El impuesto del producto, debe ser un número mayor o igual a cero o `null`.
+ * @param {number|null} producto.descuento - El descuento del producto, debe ser un número mayor o igual a cero o `null`.
+ * @param {number} producto.estado - El estado del producto, debe ser 0 (inactivo) o 1 (activo).
+ * @param {number} producto.envio - Indica si el envío está disponible, debe ser 0 (no disponible) o 1 (disponible).
+ *
+ * @returns {object|null} Un objeto con una propiedad `error` si hay un error de validación, o `null` si todos los campos son válidos.
+ * @example
+ * const producto = {
+ * idProveedor: 1,
+ * nombreComun: 'Producto X',
+ * nombreComercial: 'Producto X Comercial',
+ * descripcion: 'Descripción del producto',
+ * marca: 'Marca X',
+ * modelo: 'Modelo 123',
+ * tipoProducto: 'Tipo A',
+ * precioPuntos: 100,
+ * precioCliente: 200.50,
+ * precioVenta: 250,
+ * costo: 150,
+ * impuesto: 25,
+ * descuento: 10,
+ * estado: 1,
+ * envio: 1,
+ * };
+ *
+ * const resultado = validarProducto(producto);
+ * console.log(resultado); // null si todo está bien, o un objeto de error si algo es inválido
+ */
+// prettier-ignore
+module.exports = (producto) => {
+ if (
+ producto.idProveedor !== null
+ && (typeof producto.idProveedor !== 'number'
+ || producto.idProveedor <= 0
+ || !Number.isInteger(producto.idProveedor))
+ ) {
+ return { error: 'idProveedor debe ser un número entero positivo o NULL.' };
+ }
+
+ if (
+ !producto.nombreComun
+ || typeof producto.nombreComun !== 'string'
+ || producto.nombreComun.length > 100
+ ) {
+ return {
+ error: 'nombreComun es requerido, debe ser una cadena de texto y no exceder 100 caracteres.',
+ };
+ }
+
+ if (
+ producto.nombreComercial !== null
+ && (typeof producto.nombreComercial !== 'string' || producto.nombreComercial.length > 150)
+ ) {
+ return {
+ error: 'nombreComercial debe ser una cadena de texto o NULL y no exceder 150 caracteres.',
+ };
+ }
+
+ if (
+ producto.descripcion !== null
+ && (typeof producto.descripcion !== 'string' || producto.descripcion.length > 1000)
+ ) {
+ return {
+ error: 'descripcion debe ser una cadena de texto o NULL y no exceder 1000 caracteres.',
+ };
+ }
+
+ if (
+ producto.marca !== null
+ && (typeof producto.marca !== 'string' || producto.marca.length > 100)
+ ) {
+ return { error: 'marca debe ser una cadena de texto o NULL y no exceder 100 caracteres.' };
+ }
+
+ if (
+ producto.modelo !== null
+ && (typeof producto.modelo !== 'string' || producto.modelo.length > 100)
+ ) {
+ return { error: 'modelo debe ser una cadena de texto o NULL y no exceder 100 caracteres.' };
+ }
+
+ if (
+ producto.tipoProducto !== null
+ && (typeof producto.tipoProducto !== 'string' || producto.tipoProducto.length > 50)
+ ) {
+ return {
+ error: 'tipoProducto debe ser una cadena de texto o NULL y no exceder 50 caracteres.',
+ };
+ }
+
+ const camposNumericos = [
+ 'precioPuntos',
+ 'precioCliente',
+ 'precioVenta',
+ 'costo',
+ 'impuesto',
+ 'descuento',
+ ];
+
+ for (const campo of camposNumericos) {
+ if (
+ producto[campo] !== null
+ && (typeof producto[campo] !== 'number'
+ || (campo === 'precioPuntos' && !Number.isInteger(producto[campo]))
+ || (campo !== 'precioPuntos' && producto[campo] < 0))
+ ) {
+ return { error: `${campo} debe ser un número válido y mayor o igual a cero.` };
+ }
+ }
+
+ if (producto.estado !== undefined && producto.estado !== 0 && producto.estado !== 1) {
+ return { error: 'estado debe ser 0 (inactivo) o 1 (activo).' };
+ }
+
+ if (producto.envio !== undefined && producto.envio !== 0 && producto.envio !== 1) {
+ return { error: 'envio debe ser 0 (no disponible) o 1 (disponible).' };
+ }
+
+ return null;
+};
diff --git a/Utilidades/Intermediarios/Validaciones/validarProductoImportado.js b/Utilidades/Intermediarios/Validaciones/validarProductoImportado.js
new file mode 100644
index 00000000..1fd8e2b3
--- /dev/null
+++ b/Utilidades/Intermediarios/Validaciones/validarProductoImportado.js
@@ -0,0 +1,181 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+/**
+ * Valida los campos de un producto.
+ *
+ * Esta función valida los diferentes campos de un objeto `producto` asegurándose de que cumplan con los tipos y restricciones especificados. Si algún campo no cumple con las condiciones, se devuelve un objeto de error con un mensaje específico. Si todos los campos son válidos, se retorna `null`.
+ *
+ * @param {object} producto - El objeto que representa un producto a validar.
+ * @param {number|null} producto.idProveedor - El ID del proveedor, debe ser un número entero positivo o `null`.
+ * @param {string} producto.nombreComun - El nombre común del producto, debe ser una cadena de texto de máximo 100 caracteres.
+ * @param {string|null} producto.nombreComercial - El nombre comercial del producto, debe ser una cadena de texto de máximo 150 caracteres o `null`.
+ * @param {string|null} producto.descripcion - Descripción del producto, debe ser una cadena de texto de máximo 1000 caracteres o `null`.
+ * @param {string|null} producto.marca - La marca del producto, debe ser una cadena de texto de máximo 100 caracteres o `null`.
+ * @param {string|null} producto.modelo - El modelo del producto, debe ser una cadena de texto de máximo 100 caracteres o `null`.
+ * @param {string|null} producto.tipoProducto - El tipo de producto, debe ser una cadena de texto de máximo 50 caracteres o `null`.
+ * @param {number|null} producto.precioPuntos - El precio en puntos, debe ser un número entero positivo o `null`.
+ * @param {number|null} producto.precioCliente - El precio para el cliente, debe ser un número mayor o igual a cero o `null`.
+ * @param {number|null} producto.precioVenta - El precio de venta, debe ser un número mayor o igual a cero o `null`.
+ * @param {number|null} producto.costo - El costo del producto, debe ser un número mayor o igual a cero o `null`.
+ * @param {number|null} producto.impuesto - El impuesto del producto, debe ser un número mayor o igual a cero o `null`.
+ * @param {number|null} producto.descuento - El descuento del producto, debe ser un número mayor o igual a cero o `null`.
+ * @param {number} producto.estado - El estado del producto, debe ser 0 (inactivo) o 1 (activo).
+ * @param {number} producto.envio - Indica si el envío está disponible, debe ser 0 (no disponible) o 1 (disponible).
+ *
+ * @returns {object|null} Un objeto con una propiedad `error` si hay un error de validación, o `null` si todos los campos son válidos.
+ * @example
+ * const producto = {
+ * idProveedor: 1,
+ * nombreComun: 'Producto X',
+ * nombreComercial: 'Producto X Comercial',
+ * descripcion: 'Descripción del producto',
+ * marca: 'Marca X',
+ * modelo: 'Modelo 123',
+ * tipoProducto: 'Tipo A',
+ * precioPuntos: 100,
+ * precioCliente: 200.50,
+ * precioVenta: 250,
+ * costo: 150,
+ * impuesto: 25,
+ * descuento: 10,
+ * estado: 1,
+ * envio: 1,
+ * };
+ *
+ * const resultado = validarProducto(producto);
+ * console.log(resultado); // null si todo está bien, o un objeto de error si algo es inválido
+ */
+// prettier-ignore
+module.exports = (producto) => {
+ if (
+ producto.idProveedor !== null
+ && (
+ typeof producto.idProveedor !== 'number'
+ || producto.idProveedor <= 0
+ || producto.idProveedor % 1 !== 0
+ )
+ ) {
+ return { error: 'idProveedor debe ser un número entero positivo o NULL.' };
+ }
+
+ if (
+ !producto.nombreComun
+ || typeof producto.nombreComun !== 'string'
+ || producto.nombreComun.length > 100
+ ) {
+ return {
+ error: 'nombreProducto es requerido, debe ser una cadena de texto y no exceder 100 caracteres.',
+ };
+ }
+
+ if (
+ !producto.nombreComercial
+ || typeof producto.nombreComercial !== 'string'
+ || producto.nombreComercial.length > 100
+ ) {
+ return {
+ error: 'nombreComercial es requerido, debe ser una cadena de texto y no exceder 100 caracteres.',
+ };
+ }
+
+ if (
+ producto.descripcion !== null
+ && (typeof producto.descripcion !== 'string' || producto.descripcion.length > 1000 || producto.descripcion.trim() === '')
+ ) {
+ return {
+ error: 'descripcion debe ser una cadena de texto y no exceder 1000 caracteres.',
+ };
+ }
+
+ if (
+ producto.marca !== null
+ && (typeof producto.marca !== 'string' || producto.marca.length > 100 || producto.marca.trim() === '')
+ ) {
+ return { error: 'marca debe ser una cadena de texto y no exceder 100 caracteres.' };
+ }
+
+ if (
+ producto.modelo !== null
+ && (typeof producto.modelo !== 'string' || producto.modelo.length > 100 || producto.modelo.trim() === '')
+ ) {
+ return { error: 'modelo debe ser una cadena de texto y no exceder 100 caracteres.' };
+ }
+
+ if (
+ producto.tipoProducto !== null
+ && (typeof producto.tipoProducto !== 'string' || producto.tipoProducto.length > 50 || producto.tipoProducto.trim() === '')
+ ) {
+ return {
+ error: 'tipoProducto debe ser una cadena de texto y no exceder 50 caracteres.',
+ };
+ }
+
+ if (
+ typeof producto.costo !== 'number'
+ || producto.costo < 0
+ || Number.isNaN(producto.costo)
+ ) {
+ return {
+ error: 'costo debe ser un número mayor o igual a cero',
+ };
+ }
+
+ if (
+ typeof producto.precioVenta !== 'number'
+ || producto.precioVenta < 0
+ || Number.isNaN(producto.precioVenta)
+ ) {
+ return {
+ error: 'precioVenta debe ser un número mayor o igual a cero',
+ };
+ }
+
+ if (
+ typeof producto.precioCliente !== 'number'
+ || producto.precioCliente < 0
+ || Number.isNaN(producto.precioCliente)
+ ) {
+ return {
+ error: 'precioCliente debe ser un número mayor o igual a cero',
+ };
+ }
+
+ if (
+ typeof producto.precioPuntos !== 'number'
+ || producto.precioPuntos < 0
+ || Number.isNaN(producto.precioPuntos)
+ ) {
+ return {
+ error: 'precioPuntos debe ser un número mayor o igual a cero',
+ };
+ }
+
+ if (
+ typeof producto.impuesto !== 'number'
+ || producto.impuesto < 0
+ || Number.isNaN(producto.impuesto)
+ ) {
+ return {
+ error: 'impuesto debe ser un número mayor o igual a cero',
+ };
+ }
+
+ if (
+ typeof producto.descuento !== 'number'
+ || producto.descuento < 0 || producto.descuento > 100
+ || Number.isNaN(producto.descuento)
+ ) {
+ return {
+ error: 'descuento debe ser un número mayor o igual a cero y menor o igual a 100',
+ };
+ }
+
+ if (producto.estado !== undefined && producto.estado !== 0 && producto.estado !== 1) {
+ return { error: 'estado debe ser 0 (inactivo) o 1 (activo).' };
+ }
+
+ if (producto.envio !== undefined && producto.envio !== 0 && producto.envio !== 1) {
+ return { error: 'envio debe ser 0 (no disponible) o 1 (disponible).' };
+ }
+
+ return null;
+};
diff --git a/Utilidades/Intermediarios/Validaciones/validarProveedor.js b/Utilidades/Intermediarios/Validaciones/validarProveedor.js
new file mode 100644
index 00000000..2618b3dc
--- /dev/null
+++ b/Utilidades/Intermediarios/Validaciones/validarProveedor.js
@@ -0,0 +1,84 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+/**
+ * Valida los campos de un proveedor.
+ *
+ * Esta función verifica que los campos del objeto `proveedor` cumplan con los requisitos de tipo, longitud y formato.
+ * Si algún campo no es válido, devuelve un objeto con un mensaje de error específico.
+ * Si todos los campos son válidos, retorna `null`.
+ *
+ * @param {object} proveedor - Objeto que representa al proveedor a validar.
+ * @param {string} proveedor.nombre - Nombre del proveedor (obligatorio, máximo 100 caracteres).
+ * @param {string} [proveedor.nombreCompania] - Nombre de la compañía (opcional, máximo 150 caracteres).
+ * @param {string} [proveedor.telefonoContacto] - Teléfono de contacto (opcional, máximo 20 caracteres).
+ * @param {string} [proveedor.correoContacto] - Correo electrónico de contacto (opcional, válido y máximo 100 caracteres).
+ * @param {string} [proveedor.direccion] - Dirección del proveedor (opcional, máximo 200 caracteres).
+ * @param {string} [proveedor.codigoPostal] - Código postal (opcional, máximo 20 caracteres).
+ * @param {string} [proveedor.pais] - País del proveedor (opcional, máximo 50 caracteres).
+ * @param {number} proveedor.estado - Estado del proveedor: 1 (activo) o 0 (inactivo).
+ *
+ * @returns {{ error: string } | null} Retorna un objeto con la propiedad `error` si hay un error de validación, o `null` si todo es válido.
+ */
+module.exports = (proveedor) => {
+ /**
+ * Verifica si un texto es válido (tipo string, no vacío, dentro del límite de caracteres).
+ *
+ * @param {string} valor - Texto a validar.
+ * @param {number} max - Longitud máxima permitida.
+ * @returns {boolean} `true` si es válido, `false` en caso contrario.
+ */
+ // prettier-ignore
+ const esTextoValido = (valor, max) => typeof valor === 'string' && valor.trim().length > 0 && valor.trim().length <= max;
+
+ if (!esTextoValido(proveedor.nombre, 100)) {
+ return {
+ error: 'nombre es obligatorio y debe ser una cadena de texto de máximo 100 caracteres.',
+ };
+ }
+
+ if (proveedor.nombreCompania != null && !esTextoValido(proveedor.nombreCompania, 150)) {
+ return {
+ error: 'nombreCompania debe ser una cadena de texto no vacía de máximo 150 caracteres.',
+ };
+ }
+
+ if (proveedor.telefonoContacto != null && !esTextoValido(proveedor.telefonoContacto, 20)) {
+ return {
+ error: 'telefonoContacto debe ser una cadena de texto no vacía de máximo 20 caracteres.',
+ };
+ }
+
+ // prettier-ignore
+ if (proveedor.correoContacto != null) {
+ const correo = proveedor.correoContacto.trim();
+ const regexCorreo = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ if (
+ typeof correo !== 'string'
+ || correo.length === 0
+ || correo.length > 100
+ || !regexCorreo.test(correo)
+ ) {
+ return {
+ error:
+ 'correoContacto debe ser un correo electrónico válido y con un máximo de 100 caracteres.',
+ };
+ }
+ }
+
+ if (proveedor.direccion != null && !esTextoValido(proveedor.direccion, 200)) {
+ return { error: 'direccion debe ser una cadena de texto no vacía de máximo 200 caracteres.' };
+ }
+
+ if (proveedor.codigoPostal != null && !esTextoValido(proveedor.codigoPostal, 20)) {
+ return { error: 'codigoPostal debe ser una cadena de texto no vacía de máximo 20 caracteres.' };
+ }
+
+ if (proveedor.pais != null && !esTextoValido(proveedor.pais, 50)) {
+ return { error: 'pais debe ser una cadena de texto no vacía de máximo 50 caracteres.' };
+ }
+
+ if (typeof proveedor.estado !== 'number' || (proveedor.estado !== 1 && proveedor.estado !== 0)) {
+ return { error: 'estado debe ser 1 (activo) o 0 (inactivo).' };
+ }
+
+ return null;
+};
diff --git a/Utilidades/Intermediarios/Validaciones/validarVariante.js b/Utilidades/Intermediarios/Validaciones/validarVariante.js
new file mode 100644
index 00000000..e5de5951
--- /dev/null
+++ b/Utilidades/Intermediarios/Validaciones/validarVariante.js
@@ -0,0 +1,44 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+/**
+ * Valida los campos de una variante.
+ *
+ * Esta función valida los diferentes campos de un objeto `variante` asegurándose de que cumplan con los tipos y restricciones especificadas. Si algún campo no cumple con las condiciones, se devuelve un objeto de error con un mensaje específico. Si todos los campos son válidos, se retorna `null`.
+ *
+ * @param {object} variante - El objeto que representa una variante a validar.
+ * @param {string} variante.nombreVariante - El nombre de la variante, debe ser una cadena de texto de máximo 100 caracteres.
+ * @param {string|null} variante.descripcion - La descripción de la variante, debe ser una cadena de texto de máximo 1000 caracteres o `null`.
+ *
+ * @returns {object|null} Un objeto con una propiedad `error` si hay un error de validación, o `null` si todos los campos son válidos.
+ * @example
+ * const variante = {
+ * nombreVariante: 'Tamaño L',
+ * descripcion: 'Variante para talla grande',
+ * };
+ *
+ * const resultado = validarVariante(variante);
+ * console.log(resultado); // null si todo está bien, o un objeto de error si algo es inválido
+ */
+// prettier-ignore
+module.exports = (variante) => {
+ if (
+ !variante.nombreVariante
+ || typeof variante.nombreVariante !== 'string'
+ || variante.nombreVariante.length > 100
+ ) {
+ return {
+ error:
+ 'nombreVariante es requerido, debe ser una cadena de texto y no exceder 100 caracteres.',
+ };
+ }
+
+ if (
+ variante.descripcion !== null
+ && (typeof variante.descripcion !== 'string' || variante.descripcion.length > 1000)
+ ) {
+ return {
+ error: 'descripcion debe ser una cadena de texto y no exceder 1000 caracteres.',
+ };
+ }
+
+ return null;
+};
diff --git a/Utilidades/Intermediarios/Validaciones/validarVarianteImportar.js b/Utilidades/Intermediarios/Validaciones/validarVarianteImportar.js
new file mode 100644
index 00000000..a65542f0
--- /dev/null
+++ b/Utilidades/Intermediarios/Validaciones/validarVarianteImportar.js
@@ -0,0 +1,44 @@
+//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26
+/**
+ * Valida los campos de una variante.
+ *
+ * Esta función valida los diferentes campos de un objeto `variante` asegurándose de que cumplan con los tipos y restricciones especificadas. Si algún campo no cumple con las condiciones, se devuelve un objeto de error con un mensaje específico. Si todos los campos son válidos, se retorna `null`.
+ *
+ * @param {object} variante - El objeto que representa una variante a validar.
+ * @param {string} variante.nombreVariante - El nombre de la variante, debe ser una cadena de texto de máximo 100 caracteres.
+ * @param {string|null} variante.descripcion - La descripción de la variante, debe ser una cadena de texto de máximo 1000 caracteres o `null`.
+ *
+ * @returns {object|null} Un objeto con una propiedad `error` si hay un error de validación, o `null` si todos los campos son válidos.
+ * @example
+ * const variante = {
+ * nombreVariante: 'Tamaño L',
+ * descripcion: 'Variante para talla grande',
+ * };
+ *
+ * const resultado = validarVariante(variante);
+ * console.log(resultado); // null si todo está bien, o un objeto de error si algo es inválido
+ */
+// prettier-ignore
+module.exports = (variante) => {
+ if (
+ !variante.nombreVariante
+ || typeof variante.nombreVariante !== 'string'
+ || variante.nombreVariante.length > 100
+ ) {
+ return {
+ error:
+ 'nombreVariante es requerido, debe ser una cadena de texto y no exceder 100 caracteres.',
+ };
+ }
+
+ if (
+ variante.descripcion !== null
+ && (typeof variante.descripcion !== 'string' || variante.descripcion.length > 1000 || variante.descripcion.trim() === '')
+ ) {
+ return {
+ error: 'descripcionVariante debe ser una cadena de texto y no exceder 1000 caracteres.',
+ };
+ }
+
+ return null;
+};
diff --git a/Utilidades/Intermediarios/autorizarToken.js b/Utilidades/Intermediarios/autorizarToken.js
new file mode 100644
index 00000000..09b26ed4
--- /dev/null
+++ b/Utilidades/Intermediarios/autorizarToken.js
@@ -0,0 +1,44 @@
+const jwt = require('jsonwebtoken');
+const MENSAJES_AUTENTICACION = require('@altertex/util/const/mensajesAutenticacion');
+
+/**
+ * Middleware que verifica la validez del token JWT en las cookies del cliente.
+ *
+ * Si el token no está presente, ha expirado o no es válido, se envía un error apropiado.
+ *
+ * @param {Express.Request} req - Objeto de solicitud de Express.
+ * @param {Express.Response} res - Objeto de respuesta de Express.
+ * @param {Express.NextFunction} next - Función para continuar con el siguiente middleware.
+ * @returns {Promise} Middleware de Express para autenticación por token.
+ */
+module.exports = async (req, res, next) => {
+ const token = req.cookies.token;
+
+ if (!token) {
+ return res
+ .status(MENSAJES_AUTENTICACION.TOKEN_NO_PROPORCIONADO.codigo)
+ .json({ mensaje: MENSAJES_AUTENTICACION.TOKEN_NO_PROPORCIONADO.mensaje });
+ }
+
+ try {
+ const verificado = jwt.verify(token, process.env.JWT_SECRET);
+ req.user = verificado;
+ next();
+ } catch (error) {
+ if (error.name === 'TokenExpiredError') {
+ return res
+ .status(MENSAJES_AUTENTICACION.TOKEN_EXPIRADO.codigo)
+ .json({ mensaje: MENSAJES_AUTENTICACION.TOKEN_EXPIRADO.mensaje });
+ }
+
+ if (error.name === 'JsonWebTokenError') {
+ return res
+ .status(MENSAJES_AUTENTICACION.TOKEN_INVALIDO.codigo)
+ .json({ mensaje: MENSAJES_AUTENTICACION.TOKEN_INVALIDO.mensaje });
+ }
+
+ return res
+ .status(MENSAJES_AUTENTICACION.ERROR_VALIDAR_TOKEN.codigo)
+ .json({ mensaje: MENSAJES_AUTENTICACION.ERROR_VALIDAR_TOKEN.mensaje });
+ }
+};
diff --git a/Utilidades/Intermediarios/generarSKUAuto.js b/Utilidades/Intermediarios/generarSKUAuto.js
new file mode 100644
index 00000000..d8ffb993
--- /dev/null
+++ b/Utilidades/Intermediarios/generarSKUAuto.js
@@ -0,0 +1,66 @@
+/**
+ * Limpia el texto eliminando acentos, caracteres especiales y lo convierte a mayúsculas.
+ * @param {string} texto - El texto a limpiar.
+ * @returns {string} El texto limpio.
+ */
+const limpiarTexto = (texto) =>
+ (typeof texto === 'string' ? texto : '')
+ .normalize('NFD')
+ .replace(/[\u0300-\u036f]/g, '')
+ .replace(/[^a-zA-Z0-9\s]/g, '')
+ .toUpperCase();
+
+/**
+ * Obtiene un código basado en el texto proporcionado, usando la primera palabra que cumpla la longitud mínima.
+ * @param {string} texto - El texto del que se extraerá el código.
+ * @param {number} [longitud=3] - La longitud mínima del código a extraer.
+ * @returns {string} El código generado a partir del texto.
+ */
+const obtenerCodigo = (texto, longitud = 3) => {
+ const palabras = limpiarTexto(texto).split(' ');
+ for (const palabra of palabras) {
+ if (palabra.length >= longitud) return palabra.substring(0, longitud);
+ }
+ return limpiarTexto(texto).substring(0, longitud);
+};
+
+
+/**
+ * Genera un SKU basado en el nombre del producto, variante y valor de opción.
+ * @param {string} nombreProducto - El nombre del producto.
+ * @param {string} nombreVariante - El nombre de la variante.
+ * @param {string} valorOpcion - El valor de la opción.
+ * @returns {string} El SKU generado.
+ */
+const generarSKU = (nombreProducto, nombreVariante, valorOpcion) => {
+ try {
+ const prefijo = obtenerCodigo(nombreProducto);
+ const codigoVariante = obtenerCodigo(nombreVariante);
+ const codigoOpcion = obtenerCodigo(valorOpcion);
+ return `${prefijo}-${codigoVariante}-${codigoOpcion}`;
+ } catch {
+ return 'SKU-ERROR';
+ }
+};
+
+/**
+ * Crea una función generadora de SKUs consecutivos basada en los parámetros dados.
+ * @returns {function(string, string, string): string} Función que genera un SKU único e incremental.
+ */
+const crearGeneradorSKUConsecutivo = () => {
+ const contadorSKU = new Map();
+
+ return (nombreProducto, nombreVariante, valorOpcion) => {
+ const base = generarSKU(nombreProducto, nombreVariante, valorOpcion);
+ const actual = contadorSKU.get(base) || 0;
+ const siguiente = actual + 1;
+ contadorSKU.set(base, siguiente);
+
+ return `${base}-${String(siguiente).padStart(3, '0')}`;
+ };
+};
+
+module.exports = {
+ generarSKU, // solo base
+ crearGeneradorSKUConsecutivo // base + numeración incremental
+};
diff --git a/Utilidades/Intermediarios/limitePeticiones.js b/Utilidades/Intermediarios/limitePeticiones.js
new file mode 100644
index 00000000..57ae1e1f
--- /dev/null
+++ b/Utilidades/Intermediarios/limitePeticiones.js
@@ -0,0 +1,54 @@
+const redis = require('@altertex/config/clienteRedis');
+
+/**
+ * Genera una llave única para rastrear las peticiones diarias de un usuario por correo.
+ *
+ * @param {string} correo - Correo electrónico del usuario autenticado.
+ * @returns {string} Llave única en formato `quota:usuario::`.
+ */
+const obtenerLlave = (correo) => {
+ const fecha = new Date().toISOString().split('T')[0];
+ return `quota:usuario:${correo}:${fecha}`;
+};
+
+const PETICIONES_MAXIMAS_DIARIAS = 1500;
+
+/**
+ * Middleware que limita la cantidad de peticiones diarias que un usuario puede hacer,
+ * usando su correo electrónico como identificador.
+ *
+ * Este middleware asume que `req.user.correo` ha sido definido previamente,
+ * por ejemplo mediante un middleware de autenticación con JWT.
+ *
+ * @param {Express.Request} req - Objeto de solicitud de Express.
+ * @param {Express.Response} res - Objeto de respuesta de Express.
+ * @param {Express.NextFunction} next - Función para pasar al siguiente middleware.
+ * @returns {Promise} Retorna una promesa que se resuelve al continuar la cadena de middlewares,
+ * o responde con un error si se excede el límite o ocurre un fallo.
+ */
+const limitePeticionesDiarias = async (req, res, next) => {
+ try {
+ const correo = req.user?.correo;
+ if (!correo) {
+ return res.status(401).json({ mensaje: 'Correo del usuario no encontrado.' });
+ }
+
+ const llave = obtenerLlave(correo);
+ const contador = await redis.incr(llave);
+
+ if (contador === 1) {
+ await redis.expire(llave, 86400); // 24 horas
+ }
+
+ if (contador > PETICIONES_MAXIMAS_DIARIAS) {
+ return res.status(429).json({ mensaje: 'Límite diario de peticiones excedido para el usuario.' });
+ }
+
+ next();
+ } catch (error) {
+ console.error('Error en middleware de límite de peticiones:', error);
+ res.status(500).json({ mensaje: 'Error en el servidor.' });
+ }
+};
+
+module.exports = limitePeticionesDiarias;
diff --git a/Utilidades/Intermediarios/revisarApiKey.js b/Utilidades/Intermediarios/revisarApiKey.js
new file mode 100644
index 00000000..7c46813c
--- /dev/null
+++ b/Utilidades/Intermediarios/revisarApiKey.js
@@ -0,0 +1,31 @@
+const MENSAJES_AUTENTICACION = require('@altertex/util/const/mensajesAutenticacion');
+
+/**
+ * Middleware que valida una API key enviada en los headers de la solicitud.
+ *
+ * Si el header especificado no contiene una clave válida, se responde con un error 401.
+ *
+ * @param {string} [nombreHeader='x-api-key'] - Nombre del header que se debe verificar.
+ * @returns {function(Express.Request, Express.Response, Express.NextFunction): void} Middleware de Express que valida la API key.
+ */
+module.exports = (nombreHeader = 'x-api-key') => {
+ /**
+ * Middleware que compara la clave del header con `process.env.API_KEY`.
+ *
+ * @param {Express.Request} req - Objeto de solicitud de Express.
+ * @param {Express.Response} res - Objeto de respuesta de Express.
+ * @param {Express.NextFunction} next - Función para continuar con el siguiente middleware.
+ * @returns {void}
+ */
+ return (req, res, next) => {
+ const valorHeader = req.get(nombreHeader);
+
+ if (!valorHeader || valorHeader !== process.env.API_KEY) {
+ return res
+ .status(MENSAJES_AUTENTICACION.API_KEY_INVALIDA.codigo)
+ .json({ mensaje: MENSAJES_AUTENTICACION.API_KEY_INVALIDA.mensaje });
+ }
+
+ next();
+ };
+};
diff --git a/Utilidades/Intermediarios/validarYSanitizar.js b/Utilidades/Intermediarios/validarYSanitizar.js
new file mode 100644
index 00000000..0807b29a
--- /dev/null
+++ b/Utilidades/Intermediarios/validarYSanitizar.js
@@ -0,0 +1,46 @@
+/**
+ * @file validarInyeccionSQL.js
+ * @description Middleware para detectar posibles intentos de inyección SQL en solicitudes POST/PUT. Si se detecta, responde con un mensaje genérico.
+ */
+
+const patronSQL = /(\b(SELECT|INSERT|DELETE|UPDATE|DROP|UNION|--|;|'|"|`)\b|\bOR\b|\bAND\b)/i;
+
+/**
+ * Verifica si un objeto contiene posibles patrones de inyección SQL.
+ *
+ * @function contieneInyeccionSQL
+ * @param {any} obj - Valor a analizar. Puede ser un string, objeto o arreglo.
+ * @returns {boolean} Retorna `true` si se detecta un patrón sospechoso, `false` en caso contrario.
+ */
+function contieneInyeccionSQL(obj) {
+ if (typeof obj === 'string') {
+ return patronSQL.test(obj);
+ } else if (Array.isArray(obj)) {
+ return obj.some(contieneInyeccionSQL);
+ } else if (typeof obj === 'object' && obj !== null) {
+ return Object.values(obj).some(contieneInyeccionSQL);
+ }
+ return false;
+}
+
+/**
+ * Middleware que analiza el contenido de `req.body` para detectar patrones de inyección SQL.
+ *
+ * @function validarInyeccionSQL
+ * @param {Express.Request} req - Objeto de solicitud de Express.
+ * @param {Express.Response} res - Objeto de respuesta de Express.
+ * @param {Express.NextFunction} next - Función para continuar con la siguiente capa de middleware.
+ * @returns {void} No retorna nada directamente, pero responde con un 400 si se detecta inyección.
+ */
+function validarInyeccionSQL(req, res, next) {
+ const cuerpo = req.body;
+
+ if (contieneInyeccionSQL(cuerpo)) {
+ return res.status(400).json({
+ mensaje: 'Entrada sospechosa detectada, por favor intente de nuevo.',
+ });
+ }
+ next();
+}
+
+module.exports = validarInyeccionSQL;
diff --git a/Utilidades/Intermediarios/validarYSanitizarImagen.js b/Utilidades/Intermediarios/validarYSanitizarImagen.js
new file mode 100644
index 00000000..eb44b083
--- /dev/null
+++ b/Utilidades/Intermediarios/validarYSanitizarImagen.js
@@ -0,0 +1,50 @@
+/**
+ * @file validarYSanitizarImagen.js
+ * @description Middleware para detectar formatos no válidos de imagen.
+ */
+
+/**
+ * Retorna un middleware que valida si el archivo recibido como imagen cumple con los requisitos:
+ * - El archivo debe ser una imagen.
+ * - El formato debe ser JPG o JPEG.
+ * - El tamaño debe ser menor a 5MB.
+ *
+ * @function validarFormatoImagen
+ * @returns {function(Express.Request, Express.Response, Express.NextFunction): void}
+ * Middleware de validación de imagen.
+ */
+function validarFormatoImagen() {
+ return function (req, res, next) {
+ const imagen = req.file;
+
+ if (imagen) {
+ // Validar que el archivo corresponde a una imagen.
+ const tipo = imagen.mimetype.split('/')[0];
+ if (!tipo.match('image.*')) {
+ return res.status(400).json({
+ mensaje: 'El archivo no corresponde a una imagen.',
+ });
+ }
+
+ // Validar que el formato de la imagen es uno de los aceptados.
+ const extension = imagen.mimetype.split('/').pop();
+ if (!['jpg', 'jpeg'].includes(extension)) {
+ return res.status(400).json({
+ mensaje: 'Formato de imagen no válido. Formatos válidos: JPG',
+ });
+ }
+
+ // Validar que la imagen no pese más de 5Mb
+ const tamano = imagen.size;
+ if (tamano > 5500000) {
+ return res.status(400).json({
+ mensaje: 'Archivo muy pesado. Tamaño máximo: 5Mb.',
+ });
+ }
+ }
+
+ next();
+ };
+}
+
+module.exports = validarFormatoImagen;
diff --git a/Utilidades/Intermediarios/verificarPermisos.js b/Utilidades/Intermediarios/verificarPermisos.js
new file mode 100644
index 00000000..3ab09f09
--- /dev/null
+++ b/Utilidades/Intermediarios/verificarPermisos.js
@@ -0,0 +1,31 @@
+const MENSAJES_AUTENTICACION = require('@altertex/util/const/mensajesAutenticacion');
+
+/**
+ * Middleware para verificar si el usuario autenticado posee todos los permisos requeridos.
+ *
+ * @param {...string} permisosRequeridos - Lista de permisos necesarios para acceder al recurso.
+ * @returns {function(Express.Request, Express.Response, Express.NextFunction): void} Middleware de Express que valida los permisos del usuario.
+ */
+module.exports = (...permisosRequeridos) => {
+ return (req, res, next) => {
+ const usuario = req.user;
+
+ if (!usuario || !usuario.permisos) {
+ return res.status(MENSAJES_AUTENTICACION.USUARIO_NO_AUTENTICADO.codigo).json({
+ mensaje: MENSAJES_AUTENTICACION.USUARIO_NO_AUTENTICADO.mensaje,
+ });
+ }
+
+ const permisosUsuario = usuario.permisos;
+
+ const tienePermiso = permisosRequeridos.every((permiso) => permisosUsuario.includes(permiso));
+
+ if (!tienePermiso) {
+ return res.status(MENSAJES_AUTENTICACION.ACCESO_NO_AUTORIZADO.codigo).json({
+ mensaje: MENSAJES_AUTENTICACION.ACCESO_NO_AUTORIZADO.mensaje,
+ });
+ }
+
+ next();
+ };
+};
diff --git a/Utilidades/Servicios/correrQuery.js b/Utilidades/Servicios/correrQuery.js
new file mode 100644
index 00000000..a2f5a55f
--- /dev/null
+++ b/Utilidades/Servicios/correrQuery.js
@@ -0,0 +1,23 @@
+const conexion = require('@altertex/util/bd/db');
+
+/**
+ * Ejecuta una consulta SQL utilizando la conexión a la base de datos.
+ *
+ * @async
+ * @function
+ * @param {string} query - Consulta SQL a ejecutar.
+ * @param {Array} [params=[]] - Parámetros para la consulta preparada.
+ * @returns {Promise} Promesa que se resuelve con los resultados de la consulta o se rechaza con un error.
+ *
+ * @example
+ * const resultados = await runQuery('SELECT * FROM usuarios WHERE id = ?', [1]);
+ */
+module.exports = async (query, params = []) => {
+ try {
+ const [results] = await conexion.query(query, params);
+ return results;
+ } catch (err) {
+ console.error('Error al ejecutar la consulta:', err);
+ throw err;
+ }
+};
\ No newline at end of file
diff --git a/Utilidades/Servicios/eliminarImagenS3.js b/Utilidades/Servicios/eliminarImagenS3.js
new file mode 100644
index 00000000..533fc56b
--- /dev/null
+++ b/Utilidades/Servicios/eliminarImagenS3.js
@@ -0,0 +1,34 @@
+// Importaciones específicas del AWS SDK v3
+const { S3Client, DeleteObjectCommand } = require('@aws-sdk/client-s3');
+
+// Crear una instancia del cliente de S3
+const s3 = new S3Client({
+ region: process.env.AWS_REGION,
+ credentials: {
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
+ },
+});
+
+/**
+ * Elimina una imagen de Amazon S3.
+ *
+ * @param {string} folder - Carpeta dentro del bucket (ej. "productos/").
+ * @param {string} filename - Nombre del archivo a eliminar.
+ * @returns {Promise} Lanza un error si la eliminación falla.
+ * @throws {Error} Si ocurre un problema al eliminar el archivo de S3.
+ */
+const eliminarImagenS3 = async (folder, filename) => {
+ const params = {
+ Bucket: process.env.AWS_BUCKET_NAME,
+ Key: `${folder}${filename}`,
+ };
+
+ try {
+ await s3.send(new DeleteObjectCommand(params));
+ } catch (error) {
+ throw new Error(`Error al eliminar la imagen "${folder}${filename}" de S3: ${error.message}`);
+ }
+};
+
+module.exports = eliminarImagenS3;
diff --git a/Utilidades/Servicios/enviarS3.js b/Utilidades/Servicios/enviarS3.js
new file mode 100644
index 00000000..3cf09461
--- /dev/null
+++ b/Utilidades/Servicios/enviarS3.js
@@ -0,0 +1,31 @@
+const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
+
+const s3 = new S3Client({
+ region: process.env.AWS_REGION,
+ credentials: {
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
+ },
+});
+
+/**
+ * Carga un archivo en un bucket de Amazon S3 y devuelve la URL pública del archivo cargado.
+ * Utiliza el cliente de AWS SDK para enviar el archivo al bucket S3 configurado.
+ *
+ * @async
+ * @function subirArchivoS3
+ * @param {object} parametros - Los parámetros necesarios para cargar el archivo en S3.
+ * @param {string} parametros.Bucket - El nombre del bucket S3 donde se almacenará el archivo.
+ * @param {string} parametros.Key - El nombre del archivo que se almacenará en S3.
+ * @param {Buffer|Uint8Array|Blob|string} parametros.Body - El contenido del archivo a cargar.
+ * @param {string} [parametros.ContentType] - El tipo de contenido del archivo (opcional).
+ *
+ * @returns {Promise} La URL pública del archivo cargado en S3.
+ *
+ * @throws {Error} - Si ocurre un error al cargar el archivo en S3 o al obtener la URL.
+ */
+module.exports = async (parametros) => {
+ await s3.send(new PutObjectCommand(parametros));
+ const nombreArchivo = parametros.Key;
+ return nombreArchivo;
+};
diff --git a/Utilidades/Servicios/extraerNombreArchivoS3.js b/Utilidades/Servicios/extraerNombreArchivoS3.js
new file mode 100644
index 00000000..1149bcbc
--- /dev/null
+++ b/Utilidades/Servicios/extraerNombreArchivoS3.js
@@ -0,0 +1,12 @@
+/**
+ * Extrae el nombre real del archivo desde una URL firmada de S3.
+ * @param {string} url - URL completa del archivo en S3.
+ * @returns {string} Nombre del archivo con extensión, sin parámetros.
+ */
+const extraerNombreArchivoS3 = (url) => {
+ const partes = url.split('/');
+ const ultimaParte = partes[partes.length - 1];
+ return ultimaParte.split('?')[0]; // Elimina query params
+ };
+
+ module.exports = extraerNombreArchivoS3;
\ No newline at end of file
diff --git a/Utilidades/Servicios/generarNombreUnico.js b/Utilidades/Servicios/generarNombreUnico.js
new file mode 100644
index 00000000..81e64dc4
--- /dev/null
+++ b/Utilidades/Servicios/generarNombreUnico.js
@@ -0,0 +1,22 @@
+const crypto = require('crypto');
+const path = require('path');
+
+/**
+ * Genera un nombre de archivo único basado en la fecha actual y un hash aleatorio.
+ *
+ * Esta función utiliza la fecha actual (en milisegundos desde la época Unix) y una cadena
+ * aleatoria generada con `crypto.randomBytes`, preservando la extensión original del archivo.
+ *
+ * @function generarNombreArchivo
+ * @param {string} [nombreOriginal=""] - El nombre original del archivo, utilizado para conservar la extensión.
+ *
+ * @returns {string} Un nuevo nombre de archivo único, con la misma extensión que el original.
+ *
+ * @example
+ * const nombre = generarNombreArchivo("foto.png");
+ */
+module.exports = (nombreOriginal = '') => {
+ const ext = path.extname(nombreOriginal);
+ const randomBytes = crypto.randomBytes(16).toString('hex');
+ return `${Date.now()}-${randomBytes}${ext}`;
+};
diff --git a/Utilidades/Servicios/obtenerImagenCliente.js b/Utilidades/Servicios/obtenerImagenCliente.js
new file mode 100644
index 00000000..0d8947a3
--- /dev/null
+++ b/Utilidades/Servicios/obtenerImagenCliente.js
@@ -0,0 +1,49 @@
+const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
+const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
+
+const s3 = new S3Client({
+ region: process.env.AWS_REGION,
+ credentials: {
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
+ },
+});
+
+/**
+ * Obtiene URL firmadas temporalmente para acceder a una imagen almacenada en S3.
+ *
+ * Esta función toma un nombre de archivo, busca las imágenes
+ * dentro de esa carpeta indicadas por su `urlImagen`, y reemplaza la ruta por una URL
+ * firmada y válida por una hora, generadas con AWS S3.
+ *
+ * @async
+ * @function obtenerImagenCliente
+ * @param {string} nombreImagen - Nombre de la imagen para obtener URL de S3.
+ *
+ * @returns {string} imagenUrl
+ *
+ * @throws {Error} - Si ocurre un error al obtener la imagen desde S3.
+ */
+async function obtenerImagenCliente(nombreImagen) {
+ if (!nombreImagen) {
+ return null; // O lanzar un error si prefieres
+ }
+
+ try {
+ const parametrosImagen = {
+ Bucket: process.env.AWS_BUCKET_NAME,
+ Key: `clientes/${nombreImagen}`,
+ };
+
+ // El tiempo de expiración en segundos (ejemplo: 1 hora)
+ const imagenUrl = await getSignedUrl(s3, new GetObjectCommand(parametrosImagen), {
+ expiresIn: 3600,
+ });
+
+ return imagenUrl;
+ } catch {
+ throw new Error('Error fetching user image from S3');
+ }
+}
+
+module.exports = obtenerImagenCliente;
diff --git a/Utilidades/Servicios/obtenerImagenFolder.js b/Utilidades/Servicios/obtenerImagenFolder.js
new file mode 100644
index 00000000..e05b9077
--- /dev/null
+++ b/Utilidades/Servicios/obtenerImagenFolder.js
@@ -0,0 +1,62 @@
+const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
+const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
+
+const clienteS3 = new S3Client({
+ region: process.env.AWS_REGION,
+ credentials: {
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
+ },
+});
+
+/**
+ * Obtiene URLs firmadas temporalmente para acceder a imágenes almacenadas en S3.
+ *
+ * Esta función toma un objeto `request` y un nombre de carpeta, busca las imágenes
+ * dentro de esa carpeta indicadas por su `urlImagen`, y reemplaza esas rutas por URLs
+ * firmadas válidas por una hora, generadas con AWS S3.
+ *
+ * @async
+ * @function obtenerImagenFolder
+ * @param {object} request - Objeto que contiene los datos con las rutas de imágenes a firmar.
+ * @param {string} nombreFolder - Nombre del campo dentro del objeto `request` que contiene el arreglo con las rutas de imágenes. El último carácter (`/`) será eliminado.
+ *
+ * @returns {Promise>} Un array con los mismos objetos del array original, pero con la propiedad `urlImagen` reemplazada por la URL firmada o `null`.
+ *
+ * @throws {Error} - Si los datos del `request` no son válidos o si ocurre un error al obtener la imagen desde S3.
+ */
+async function obtenerImagenFolder(request, nombreFolder) {
+ nombreFolder = nombreFolder.slice(0, -1);
+ const Json = request[nombreFolder];
+
+ if (!Json || !Array.isArray(Json)) {
+ throw new Error('Invalid request data');
+ }
+
+ try {
+ const jsonActualizado = await Promise.all(
+ Json.map(async (folder) => {
+ if (folder.urlImagen) {
+ const comando = new GetObjectCommand({
+ Bucket: process.env.AWS_BUCKET_NAME,
+ Key: `${nombreFolder}/${folder.urlImagen}`,
+ });
+
+ folder.urlImagen = await getSignedUrl(clienteS3, comando, {
+ expiresIn: 60 * 60,
+ });
+ } else {
+ folder.urlImagen = null;
+ }
+
+ return folder;
+ })
+ );
+
+ return jsonActualizado;
+ } catch {
+ throw new Error('Error obteniendo imagen de S3');
+ }
+}
+
+module.exports = obtenerImagenFolder;
diff --git a/Utilidades/Servicios/subirImagen.js b/Utilidades/Servicios/subirImagen.js
new file mode 100644
index 00000000..49b1bb6b
--- /dev/null
+++ b/Utilidades/Servicios/subirImagen.js
@@ -0,0 +1,29 @@
+const subirArchivo = require('@altertex/util/ser/enviarS3');
+
+/**
+ * Sube un archivo al bucket de AWS S3 con un nombre y ruta específicos.
+ *
+ * @async
+ * @function
+ * @param {object} file - Archivo a subir. Debe contener las propiedades `buffer` y `mimetype`.
+ * @param {string} route - Ruta dentro del bucket donde se almacenará la imagen (por ejemplo, 'clientes').
+ * @param {string} name - Nombre base del archivo (sin extensión). Se le añadirá `.jpg` automáticamente.
+ * @returns {Promise} Retorna el resultado de la operación de subida a S3.
+ * @throws {Error} Lanza un error si ocurre un fallo al subir el archivo.
+ */
+module.exports = async (file, route, name) => {
+ if (file) {
+ const fileName = `${route}/${name}.jpg`;
+ try {
+ return await subirArchivo({
+ Bucket: process.env.AWS_BUCKET_NAME,
+ Key: fileName,
+ Body: file.buffer,
+ ContentType: file.mimetype,
+ });
+ } catch (error) {
+ console.error('Error al subir imagen: ', error);
+ throw new Error('Error al subir imagen');
+ }
+ }
+};
diff --git a/Utilidades/Servicios/verificarCodigo2FA.servicio.js b/Utilidades/Servicios/verificarCodigo2FA.servicio.js
new file mode 100644
index 00000000..31829286
--- /dev/null
+++ b/Utilidades/Servicios/verificarCodigo2FA.servicio.js
@@ -0,0 +1,32 @@
+// @file verificarCodigo2FA.servicio.js
+
+const speakeasy = require('speakeasy');
+const db = require('@altertex/util/bd/db');
+
+/**
+ * Verifica un código TOTP contra el secreto almacenado de un usuario.
+ * @param {number} idUsuario - ID del usuario que ejecuta la acción
+ * @param {string} codigo - Código TOTP ingresado (6 dígitos)
+ * @returns {Promise} true si el código es válido
+ */
+const verificarCodigo2FA = async (idUsuario, codigo) => {
+ const [resultado] = await db.query(
+ 'SELECT secret2FA FROM usuarios_2fa WHERE idUsuario = ? AND tiene2FA = true',
+ [idUsuario]
+ );
+
+ if (!resultado || resultado.length === 0) {
+ return false;
+ }
+
+ const { secret2FA } = resultado[0];
+
+ return speakeasy.totp.verify({
+ secret: secret2FA,
+ encoding: 'base32',
+ token: codigo,
+ window: 1
+ });
+};
+
+module.exports = { verificarCodigo2FA };
\ No newline at end of file
diff --git a/_tests_/Categorias/consultarListaCategorias.controller.test.js b/_tests_/Categorias/consultarListaCategorias.controller.test.js
new file mode 100644
index 00000000..c6e4b246
--- /dev/null
+++ b/_tests_/Categorias/consultarListaCategorias.controller.test.js
@@ -0,0 +1,89 @@
+/**
+ * RF[47] Consulta Lista de Categorías - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF47
+ * Mocks antes de importar el controlador
+ */
+jest.mock('@altertex/cat/repos/repositorioConsultarListaCategorias', () => ({
+ consultarListaCategorias: jest.fn(),
+}));
+
+// Importar después del mock
+const controlador = require('@altertex/cat/ctrl/consultarListaCategorias.controller');
+const repositorio = require('@altertex/cat/repos/repositorioConsultarListaCategorias');
+const MENSAJES_CATEGORIAS = require('@altertex/util/const/mensajesCategorias');
+
+describe('Controlador consultarListaCategorias', () => {
+ let req;
+ let res;
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+
+ req = {
+ user: {
+ clienteSeleccionado: '3',
+ },
+ };
+
+ res = {
+ status: jest.fn().mockReturnThis(),
+ json: jest.fn(),
+ };
+
+ jest.spyOn(console, 'error').mockImplementation(() => {}); // Evita logs
+ });
+
+ // Escenario 1: No se encuentran categorías
+ test('Debe retornar mensaje cuando no hay categorías encontradas', async () => {
+ repositorio.consultarListaCategorias.mockResolvedValue([]);
+
+ await controlador.consultarListaCategorias(req, res);
+
+ expect(repositorio.consultarListaCategorias).toHaveBeenCalledWith(3);
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_CATEGORIAS.CATEGORIAS_NO_ENCONTRADAS.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_CATEGORIAS.CATEGORIAS_NO_ENCONTRADAS.mensaje,
+ });
+ });
+
+ // Escenario 2: Lista de categorías obtenida correctamente
+ test('Debe retornar la lista de categorías cuando se obtienen con éxito', async () => {
+ const mockCategorias = [
+ {
+ idCategoria: 1,
+ nombre: 'Camisas',
+ productos: ['Camisa A', 'Camisa B'],
+ },
+ {
+ idCategoria: 2,
+ nombre: 'Pantalones',
+ productos: ['Pantalón X'],
+ },
+ ];
+
+ repositorio.consultarListaCategorias.mockResolvedValue(mockCategorias);
+
+ await controlador.consultarListaCategorias(req, res);
+
+ expect(repositorio.consultarListaCategorias).toHaveBeenCalledWith(3);
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_CATEGORIAS.LISTA_CATEGORIAS_OBTENIDA.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_CATEGORIAS.LISTA_CATEGORIAS_OBTENIDA.mensaje,
+ listaCategoria: mockCategorias,
+ });
+ });
+
+ // Escenario 3: Error inesperado en el repositorio
+ test('Debe manejar errores si falla el repositorio', async () => {
+ repositorio.consultarListaCategorias.mockRejectedValue(
+ new Error('Error de base de datos')
+ );
+
+ await controlador.consultarListaCategorias(req, res);
+
+ expect(repositorio.consultarListaCategorias).toHaveBeenCalledWith(3);
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_CATEGORIAS.ERROR_OBTENER_CATEGORIAS.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_CATEGORIAS.ERROR_OBTENER_CATEGORIAS.mensaje,
+ });
+ });
+});
\ No newline at end of file
diff --git a/_tests_/Clientes/eliminarCliente.controller.test.js b/_tests_/Clientes/eliminarCliente.controller.test.js
new file mode 100644
index 00000000..22b47d57
--- /dev/null
+++ b/_tests_/Clientes/eliminarCliente.controller.test.js
@@ -0,0 +1,92 @@
+/**
+ * RF[15] Eliminar Cliente - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF15
+ * Mocks antes de importar el controlador
+ */
+jest.mock('@altertex/cli/repos/repositorioEliminarCliente', () => ({
+ eliminarClientePorId: jest.fn(),
+}));
+jest.mock('@altertex/util/ser/eliminarImagenS3', () => jest.fn());
+jest.mock('@altertex/util/ser/extraerNombreArchivoS3', () => jest.fn());
+jest.mock('@altertex/util/ser/correrQuery', () => jest.fn());
+
+const controlador = require('@altertex/cli/ctrl/eliminarCliente.controller');
+const repositorio = require('@altertex/cli/repos/repositorioEliminarCliente');
+const eliminarImagenS3 = require('@altertex/util/ser/eliminarImagenS3');
+const extraerNombreArchivoS3 = require('@altertex/util/ser/extraerNombreArchivoS3');
+const correrQuery = require('@altertex/util/ser/correrQuery');
+const MENSAJES_CLIENTES = require('@altertex/util/const/mensajesClientes');
+
+describe('Controlador eliminarCliente', () => {
+ let req;
+ let res;
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+
+ req = {
+ body: { idCliente: '3' },
+ };
+
+ res = {
+ status: jest.fn().mockReturnThis(),
+ json: jest.fn(),
+ };
+
+ jest.spyOn(console, 'error').mockImplementation(() => {});
+ });
+
+ // Escenario 1: ID inválido
+ test('Debe retornar error si el ID de cliente es inválido', async () => {
+ req.body.idCliente = ' ';
+
+ await controlador.eliminarCliente(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_CLIENTES.CLIENTE_INVALIDO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_CLIENTES.CLIENTE_INVALIDO.mensaje,
+ });
+ });
+
+ // Escenario 2: Cliente no encontrado
+ test('Debe retornar error si el cliente no existe', async () => {
+ correrQuery.mockResolvedValue([]);
+ repositorio.eliminarClientePorId.mockResolvedValue({ affectedRows: 0 });
+
+ await controlador.eliminarCliente(req, res);
+
+ expect(repositorio.eliminarClientePorId).toHaveBeenCalledWith(3);
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_CLIENTES.CLIENTE_NO_ENCONTRADO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_CLIENTES.CLIENTE_NO_ENCONTRADO.mensaje,
+ });
+ });
+
+ // Escenario 3: Cliente eliminado correctamente con imagen
+ test('Debe eliminar al cliente y su imagen si existe', async () => {
+ correrQuery.mockResolvedValue([{ urlImagen: 'https://bucket.s3/cliente123.jpg' }]);
+ extraerNombreArchivoS3.mockReturnValue('cliente123.jpg');
+ repositorio.eliminarClientePorId.mockResolvedValue({ affectedRows: 1 });
+
+ await controlador.eliminarCliente(req, res);
+
+ expect(correrQuery).toHaveBeenCalled();
+ expect(extraerNombreArchivoS3).toHaveBeenCalledWith('https://bucket.s3/cliente123.jpg');
+ expect(eliminarImagenS3).toHaveBeenCalledWith('clientes/', 'cliente123.jpg');
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_CLIENTES.CLIENTE_ELIMINADO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_CLIENTES.CLIENTE_ELIMINADO.mensaje,
+ });
+ });
+
+ // Escenario 4: Error inesperado
+ test('Debe manejar errores inesperados en el try/catch', async () => {
+ correrQuery.mockRejectedValue(new Error('DB error'));
+
+ await controlador.eliminarCliente(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_CLIENTES.ERROR_ELIMINAR_CLIENTE.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_CLIENTES.ERROR_ELIMINAR_CLIENTE.mensaje,
+ });
+ });
+});
diff --git a/_tests_/Clientes/leerCliente.controller.test.js b/_tests_/Clientes/leerCliente.controller.test.js
new file mode 100644
index 00000000..953b7318
--- /dev/null
+++ b/_tests_/Clientes/leerCliente.controller.test.js
@@ -0,0 +1,124 @@
+/**
+ * RF[13] Leer Cliente - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/rf13/
+ * Mocks antes de importar el controlador
+ */
+jest.mock('@altertex/cli/repos/repositorioLeerCliente', () => ({
+ obtenerClientePorId: jest.fn(),
+}));
+jest.mock('@altertex/util/ser/obtenerImagenCliente', () => jest.fn());
+
+const controlador = require('@altertex/cli/ctrl/leerCliente.controller');
+const repositorio = require('@altertex/cli/repos/repositorioLeerCliente');
+const obtenerImagenCliente = require('@altertex/util/ser/obtenerImagenCliente');
+const MENSAJES_CLIENTES = require('@altertex/util/const/mensajesClientes');
+
+describe('Controlador leerCliente', () => {
+ let req;
+ let res;
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+
+ req = {
+ body: { idCliente: '7' },
+ };
+
+ res = {
+ status: jest.fn().mockReturnThis(),
+ json: jest.fn(),
+ };
+
+ jest.spyOn(console, 'error').mockImplementation(() => {});
+ });
+
+ // Escenario 1: ID inválido
+ test('Debe retornar error si el ID es inválido', async () => {
+ req.body.idCliente = ' ';
+
+ await controlador.leerCliente(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_CLIENTES.PARAMETROS_INVALIDOS.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_CLIENTES.PARAMETROS_INVALIDOS.mensaje,
+ });
+ });
+
+ // Escenario 2: Cliente no encontrado
+ test('Debe retornar error si el cliente no existe', async () => {
+ repositorio.obtenerClientePorId.mockResolvedValue(null);
+
+ await controlador.leerCliente(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_CLIENTES.CLIENTE_NO_ENCONTRADO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_CLIENTES.CLIENTE_NO_ENCONTRADO.mensaje,
+ });
+ });
+
+ // Escenario 3: Cliente encontrado con imagen exitosa
+ test('Debe retornar cliente completo con imagen si todo funciona bien', async () => {
+ const mockCliente = {
+ idCliente: 7,
+ nombreLegal: 'Tech S.A.',
+ nombreVisible: 'Tech Store',
+ empleados: [],
+ usuariosAsignados: [],
+ numeroEmpleados: 10,
+ urlImagen: 'https://bucket.s3/cliente.jpg',
+ };
+
+ repositorio.obtenerClientePorId.mockResolvedValue(mockCliente);
+ obtenerImagenCliente.mockResolvedValue('https://signed-url.com/cliente.jpg');
+
+ await controlador.leerCliente(req, res);
+
+ expect(obtenerImagenCliente).toHaveBeenCalledWith(mockCliente.urlImagen);
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_CLIENTES.CONSULTA_EXITOSA.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_CLIENTES.CONSULTA_EXITOSA.mensaje,
+ cliente: {
+ ...mockCliente,
+ imagenCliente: 'https://signed-url.com/cliente.jpg',
+ },
+ });
+ });
+
+ // Escenario 4: Cliente encontrado, pero falla obtenerImagenCliente
+ test('Debe retornar imagen placeholder si obtenerImagenCliente falla', async () => {
+ const mockCliente = {
+ idCliente: 7,
+ nombreLegal: 'Tech S.A.',
+ nombreVisible: 'Tech Store',
+ empleados: [],
+ usuariosAsignados: [],
+ numeroEmpleados: 10,
+ urlImagen: 'https://bucket.s3/cliente.jpg',
+ };
+
+ repositorio.obtenerClientePorId.mockResolvedValue(mockCliente);
+ obtenerImagenCliente.mockRejectedValue(new Error('Fallo S3'));
+
+ await controlador.leerCliente(req, res);
+
+ expect(obtenerImagenCliente).toHaveBeenCalledWith(mockCliente.urlImagen);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_CLIENTES.CONSULTA_EXITOSA.mensaje,
+ cliente: {
+ ...mockCliente,
+ imagenCliente: '/placeholder.png',
+ },
+ });
+ });
+
+ // Escenario 5: Error inesperado
+ test('Debe manejar error inesperado del repositorio', async () => {
+ repositorio.obtenerClientePorId.mockRejectedValue(new Error('DB error'));
+
+ await controlador.leerCliente(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_CLIENTES.ERROR_CONSULTAR_CLIENTE.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_CLIENTES.ERROR_CONSULTAR_CLIENTE.mensaje,
+ });
+ });
+});
\ No newline at end of file
diff --git a/_tests_/Cuotas/Controladores/crearCuota.controller.test.js b/_tests_/Cuotas/Controladores/crearCuota.controller.test.js
new file mode 100644
index 00000000..5104d937
--- /dev/null
+++ b/_tests_/Cuotas/Controladores/crearCuota.controller.test.js
@@ -0,0 +1,103 @@
+/**
+ * Mocks antes de importar el controlador
+ */
+jest.mock('@altertex/cuota/ctrl/validarCuotaSet', () => ({
+ validarCuotaSet: jest.fn(),
+}));
+jest.mock('@altertex/cuota/repos/crearCuotaRepositorio', () => ({
+ crearCuota: jest.fn(),
+}));
+
+// Importar después de los mocks
+const controladorCrearCuota = require('@altertex/cuota/ctrl/crearCuota.controller');
+const { validarCuotaSet } = require('@altertex/cuota/ctrl/validarCuotaSet');
+const { crearCuota } = require('@altertex/cuota/repos/crearCuotaRepositorio');
+
+describe('Controlador de Crear Cuota', () => {
+ let req;
+ let res;
+ let originalDate;
+
+ const dataMock = {
+ nombre: 'Plan Básico',
+ descripcion: 'Plan básico para clientes nuevos',
+ periodoRenovacion: 'mensual',
+ renovacionHabilitada: true,
+ productosYLimite: [
+ { idProducto: 1, limite: 100, limiteActual: 100 },
+ { idProducto: 2, limite: 50, limiteActual: 50 },
+ ],
+ idCliente: 102,
+ };
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+
+ // Guardar la Date original
+ originalDate = global.Date;
+
+ // Mock de fecha
+ const mockDate = new Date('2023-05-15T00:00:00Z');
+ global.Date = class extends Date {
+ constructor() {
+ super();
+ return mockDate;
+ }
+ };
+
+ // Mock de req y res
+ req = {
+ body: dataMock,
+ user: {
+ clienteSeleccionado: 102, // o el valor necesario para el controlador
+ },
+ };
+ res = {
+ status: jest.fn().mockReturnThis(),
+ json: jest.fn(),
+ };
+ });
+
+ afterEach(() => {
+ // Restaurar Date original
+ global.Date = originalDate;
+ });
+
+ test('Debe crear un cuota set exitosamente', async () => {
+ const cuotaSetIdMock = 123;
+ crearCuota.mockResolvedValue(cuotaSetIdMock);
+
+ await controladorCrearCuota.crearCuota(req, res);
+
+ expect(validarCuotaSet).toHaveBeenCalledWith(dataMock.nombre, dataMock.productosYLimite, res);
+
+ expect(crearCuota).toHaveBeenCalledWith({
+ ...dataMock,
+ ultimaActualizacion: '2023-05-15',
+ });
+
+ expect(res.status).toHaveBeenCalledWith(201);
+ expect(res.json).toHaveBeenCalledWith({
+ exito: 'Cuota set creado exitosamente',
+ });
+ });
+
+ test('Debe manejar errores de validación', async () => {
+ // Simula que validarCuotaSet lanza un error
+ validarCuotaSet.mockImplementation(() => {
+ throw new Error('Error de validación');
+ });
+
+ await controladorCrearCuota.crearCuota(req, res);
+
+ expect(validarCuotaSet).toHaveBeenCalled();
+ expect(crearCuota).not.toHaveBeenCalled();
+ expect(res.status).toHaveBeenCalledWith(400);
+ expect(res.json).toHaveBeenCalledWith(
+ expect.objectContaining({
+ error: 'Error creando cuota set',
+ detalle: expect.stringContaining('Error de validación'),
+ })
+ );
+ });
+});
diff --git a/_tests_/Empleados/exportarEmpleados.controller.test.js b/_tests_/Empleados/exportarEmpleados.controller.test.js
new file mode 100644
index 00000000..3dd61936
--- /dev/null
+++ b/_tests_/Empleados/exportarEmpleados.controller.test.js
@@ -0,0 +1,106 @@
+/**
+ * RF[59] Exportar Empleados - https://codeandco-wiki.netlify.app/docs/next/proyectos/textiles/documentacion/requisitos/RF59
+ * Mocks antes de importar el controlador
+ */
+jest.mock('@altertex/emp/repos/repositorioExportarEmpleado', () => ({
+ obtenerEmpleadosExportacion: jest.fn(),
+}));
+
+const controlador = require('@altertex/emp/ctrl/exportarEmpleados.controller');
+const repositorio = require('@altertex/emp/repos/repositorioExportarEmpleado');
+const MENSAJES_EMPLEADOS = require('@altertex/util/const/mensajesEmpleados');
+
+describe('Controlador exportarEmpleados', () => {
+ let req;
+ let res;
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+
+ req = {
+ user: { clienteSeleccionado: '5' },
+ body: { idsEmpleado: [1, 2] },
+ };
+
+ res = {
+ status: jest.fn().mockReturnThis(),
+ json: jest.fn(),
+ };
+
+ jest.spyOn(console, 'error').mockImplementation(() => {});
+ });
+
+ // Escenario 1: No se envían IDs
+ test('Debe retornar error si no se envían empleados a exportar', async () => {
+ req.body.idsEmpleado = [];
+
+ await controlador.exportarEmpleados(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_EMPLEADOS.PARAMETROS_INVALIDOS.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: 'Debes seleccionar al menos un empleado para exportar.',
+ });
+ });
+
+ // Escenario 2: No se encuentran empleados en la base
+ test('Debe retornar mensaje si no hay empleados encontrados', async () => {
+ repositorio.obtenerEmpleadosExportacion.mockResolvedValue([]);
+
+ await controlador.exportarEmpleados(req, res);
+
+ expect(repositorio.obtenerEmpleadosExportacion).toHaveBeenCalledWith(5, [1, 2]);
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_EMPLEADOS.EMPLEADOS_NO_ENCONTRADOS.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_EMPLEADOS.EMPLEADOS_NO_ENCONTRADOS.mensaje,
+ csv: '',
+ });
+ });
+
+ // Escenario 3: Exportación exitosa
+ test('Debe retornar CSV con empleados exportados correctamente', async () => {
+ const empleadosMock = [
+ {
+ idEmpleado: 1,
+ nombreCompleto: 'Juan Pérez',
+ correoElectronico: 'juan@example.com',
+ numeroTelefono: '1234567890',
+ direccion: 'Calle Falsa 123',
+ fechaNacimiento: '1990-01-01',
+ genero: 'M',
+ estatus: 'Activo',
+ numeroEmergencia: '0987654321',
+ areaTrabajo: 'Ventas',
+ posicion: 'Ejecutivo',
+ cantidadPuntos: 200,
+ antiguedad: '2020-01-01',
+ },
+ ];
+
+ repositorio.obtenerEmpleadosExportacion.mockResolvedValue(empleadosMock);
+
+ await controlador.exportarEmpleados(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_EMPLEADOS.LISTA_EMPLEADOS_EXPORTADA.codigo);
+ const csvLlamado = res.json.mock.calls[0][0].csv;
+
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_EMPLEADOS.LISTA_EMPLEADOS_EXPORTADA.mensaje,
+ csv: expect.stringContaining('Juan Pérez'), // Verifica contenido parcial
+ });
+
+ expect(csvLlamado.startsWith('\uFEFF')).toBe(true); // CSV debe tener BOM
+ });
+
+ // Escenario 4: Error inesperado
+ test('Debe manejar errores del repositorio', async () => {
+ repositorio.obtenerEmpleadosExportacion.mockRejectedValue(new Error('Error de DB'));
+
+ await controlador.exportarEmpleados(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_EMPLEADOS.ERROR_EXPORTAR_EMPLEADOS.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_EMPLEADOS.ERROR_EXPORTAR_EMPLEADOS.mensaje,
+ csv: '',
+ });
+ });
+});
\ No newline at end of file
diff --git a/_tests_/Empleados/leerGrupoEmpleados.controller.test.js b/_tests_/Empleados/leerGrupoEmpleados.controller.test.js
new file mode 100644
index 00000000..d9e6f33b
--- /dev/null
+++ b/_tests_/Empleados/leerGrupoEmpleados.controller.test.js
@@ -0,0 +1,98 @@
+/**
+ * RF[23] Lee grupo de empleados - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF23
+ * Mocks antes de importar el controlador
+ */
+jest.mock('@altertex/emp/repos/repositorioLeerGrupoDeEmpleados', () => ({
+ obtenerGrupoEmpleadosPorId: jest.fn(),
+}));
+
+// Importar después de los mocks
+const controladorLeerGrupoEmpleados = require('@altertex/emp/ctrl/leerGrupoEmpleados.controller');
+const repositorio = require('@altertex/emp/repos/repositorioLeerGrupoDeEmpleados');
+const MENSAJES_GRUPO_EMPLEADOS = require('@altertex/util/const/mensajesGrupoEmpleados');
+
+describe('Controlador de Leer Grupo de Empleados', () => {
+ let req;
+ let res;
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+
+ // Mock de req y res
+ req = {
+ body: {
+ idGrupo: 5,
+ },
+ };
+
+ res = {
+ status: jest.fn().mockReturnThis(),
+ json: jest.fn(),
+ };
+
+ // Evitar mostrar errores en consola durante las pruebas
+ jest.spyOn(console, 'error').mockImplementation(() => {});
+ });
+
+ // Escenario 1: ID de grupo inválido
+ test('Debe retornar error cuando el ID de grupo es inválido', async () => {
+ req.body.idGrupo = 'invalido';
+
+ await controladorLeerGrupoEmpleados.leerGrupoEmpleados(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_GRUPO_EMPLEADOS.PARAMETROS_INVALIDOS.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_GRUPO_EMPLEADOS.PARAMETROS_INVALIDOS.mensaje,
+ });
+ });
+
+ // Escenario 2: Grupo no encontrado en la base de datos
+ test('Debe retornar error cuando el grupo no es encontrado', async () => {
+ repositorio.obtenerGrupoEmpleadosPorId.mockResolvedValue(null);
+
+ await controladorLeerGrupoEmpleados.leerGrupoEmpleados(req, res);
+
+ expect(repositorio.obtenerGrupoEmpleadosPorId).toHaveBeenCalledWith(5);
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_GRUPO_EMPLEADOS.GRUPO_NO_ENCONTRADO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_GRUPO_EMPLEADOS.GRUPO_NO_ENCONTRADO.mensaje,
+ });
+ });
+
+ // Escenario 3: Grupo encontrado exitosamente
+ test('Debe retornar el grupo cuando es encontrado exitosamente', async () => {
+ const mockGrupo = {
+ idGrupo: 5,
+ nombre: 'Grupo de Ventas',
+ descripcion: 'Equipo de ventas regional',
+ setsProductos: ['Producto A', 'Producto B'],
+ empleados: ['Juan Pérez', 'Ana García'],
+ };
+
+ repositorio.obtenerGrupoEmpleadosPorId.mockResolvedValue(mockGrupo);
+
+ await controladorLeerGrupoEmpleados.leerGrupoEmpleados(req, res);
+
+ expect(repositorio.obtenerGrupoEmpleadosPorId).toHaveBeenCalledWith(5);
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_GRUPO_EMPLEADOS.GRUPO_OBTENIDO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_GRUPO_EMPLEADOS.GRUPO_OBTENIDO.mensaje,
+ grupoEmpleados: mockGrupo,
+ });
+ });
+
+ // Escenario 4: Error al obtener el grupo (excepción en el repositorio)
+ test('Debe manejar errores en la consulta al repositorio', async () => {
+ repositorio.obtenerGrupoEmpleadosPorId.mockRejectedValue(
+ new Error('Error en la base de datos')
+ );
+
+ await controladorLeerGrupoEmpleados.leerGrupoEmpleados(req, res);
+
+ expect(repositorio.obtenerGrupoEmpleadosPorId).toHaveBeenCalledWith(5);
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_GRUPO_EMPLEADOS.ERROR_OBTENER_GRUPO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_GRUPO_EMPLEADOS.ERROR_OBTENER_GRUPO.mensaje,
+ });
+ });
+});
diff --git a/_tests_/Eventos/Controladores/crearEvento.controller.test.js b/_tests_/Eventos/Controladores/crearEvento.controller.test.js
new file mode 100644
index 00000000..68c0613d
--- /dev/null
+++ b/_tests_/Eventos/Controladores/crearEvento.controller.test.js
@@ -0,0 +1,185 @@
+// Mock del repositorio
+jest.mock('@altertex/eve/repos/repositorioCrearEvento', () => ({
+ crearEvento: jest.fn(),
+}));
+
+// Función a probar
+const { crearEvento } = require('@altertex/eve/ctrl/crearEvento.controller');
+const repositorio = require('@altertex/eve/repos/repositorioCrearEvento'); // Mock del repositorio
+const MENSAJES_EVENTOS = require('@altertex/util/const/mensajesEventos');
+
+// Pruebas
+describe('Controlador de Crear Evento', () => {
+ let req;
+ let res;
+
+ beforeEach(() => {
+ // Reset de los mocks
+ jest.clearAllMocks();
+
+ // Mock de req y res
+ req = {
+ body: {},
+ };
+
+ res = {
+ status: jest.fn().mockReturnThis(),
+ json: jest.fn(),
+ cookie: jest.fn(),
+ };
+ });
+
+ test('Campos requeridos vacíos', async () => {
+ // Arrange - Solo faltan los campos requeridos
+ req.body = {
+ idCliente: '',
+ nombre: '',
+ descripcion: '', // Opcional - está bien que esté vacío
+ puntos: '',
+ multiplicador: '',
+ periodoRenovacion: '', // Opcional - está bien que esté vacío
+ renovacion: false,
+ };
+
+ // Act
+ await crearEvento(req, res);
+
+ // Assert
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_EVENTOS.PARAMETROS_INVALIDOS.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ codigo: MENSAJES_EVENTOS.PARAMETROS_INVALIDOS.codigo,
+ mensaje: MENSAJES_EVENTOS.PARAMETROS_INVALIDOS.mensaje,
+ });
+ });
+
+ test('Evento con campos opcionales vacíos', async () => {
+ // Arrange - Campos requeridos llenos, opcionales vacíos
+ req.body = {
+ idCliente: '1',
+ nombre: 'Evento de prueba',
+ descripcion: '', // Campo opcional vacío
+ puntos: '100',
+ multiplicador: '1.5',
+ periodoRenovacion: '', // Campo opcional vacío
+ renovacion: true,
+ };
+
+ const eventoCreado = {
+ id: 1,
+ nombre: 'Evento de prueba'
+ };
+
+ repositorio.crearEvento.mockResolvedValue({ evento: eventoCreado });
+
+ // Act
+ await crearEvento(req, res);
+
+ // Assert
+ expect(repositorio.crearEvento).toHaveBeenCalledWith({
+ idCliente: 1,
+ nombre: 'Evento de prueba',
+ descripcion: null, // Se convierte a null cuando está vacío
+ puntos: 100,
+ multiplicador: 1.5,
+ periodoRenovacion: null, // Se convierte a null cuando está vacío
+ renovacion: 1,
+ });
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_EVENTOS.EVENTO_CREADO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ codigo: MENSAJES_EVENTOS.EVENTO_CREADO.codigo,
+ mensaje: MENSAJES_EVENTOS.EVENTO_CREADO.mensaje,
+ evento: eventoCreado,
+ });
+ });
+
+ test('Campos inválidos', async () => {
+ // Arrange
+ req.body = {
+ idCliente: 'abc',
+ nombre: 'Evento de prueba',
+ descripcion: 'Descripción del evento',
+ puntos: 'cien',
+ multiplicador: 'uno punto cinco',
+ periodoRenovacion: 'mensual',
+ renovacion: 'sí',
+ };
+
+ // Act
+ await crearEvento(req, res);
+
+ // Assert
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_EVENTOS.PARAMETROS_INVALIDOS.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ codigo: MENSAJES_EVENTOS.PARAMETROS_INVALIDOS.codigo,
+ mensaje: 'El ID del cliente debe ser un número válido mayor a 0.',
+ });
+ });
+
+ test('Cliente inexistente (error del repositorio)', async () => {
+ // Arrange
+ req.body = {
+ idCliente: '999',
+ nombre: 'Evento de prueba',
+ descripcion: 'Descripción del evento',
+ puntos: '100',
+ multiplicador: '1.5',
+ periodoRenovacion: 'mensual',
+ renovacion: true,
+ };
+
+ // Simulamos un error específico del repositorio
+ repositorio.crearEvento.mockRejectedValue(new Error(MENSAJES_EVENTOS.ERROR_CLIENTE_NO_EXISTE.mensaje));
+
+ // Act
+ await crearEvento(req, res);
+
+ // Assert
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_EVENTOS.ERROR_CREAR_EVENTO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ codigo: MENSAJES_EVENTOS.ERROR_CREAR_EVENTO.codigo,
+ mensaje: MENSAJES_EVENTOS.ERROR_CLIENTE_NO_EXISTE.mensaje,
+ });
+ });
+
+ test('Evento creado exitosamente', async () => {
+ // Arrange
+ req.body = {
+ idCliente: '1',
+ nombre: 'Evento de prueba',
+ descripcion: 'Descripción del evento',
+ puntos: '100',
+ multiplicador: '1.5',
+ periodoRenovacion: 'mensual',
+ renovacion: true,
+ };
+
+ const eventoCreado = {
+ id: 1,
+ nombre: 'Evento de prueba'
+ };
+
+ repositorio.crearEvento.mockResolvedValue({ evento: eventoCreado });
+
+ // Act
+ await crearEvento(req, res);
+
+ // Assert
+ expect(repositorio.crearEvento).toHaveBeenCalledWith({
+ idCliente: 1,
+ nombre: 'Evento de prueba',
+ descripcion: 'Descripción del evento',
+ puntos: 100,
+ multiplicador: 1.5,
+ periodoRenovacion: 'mensual',
+ renovacion: 1,
+ });
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_EVENTOS.EVENTO_CREADO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ codigo: MENSAJES_EVENTOS.EVENTO_CREADO.codigo,
+ mensaje: MENSAJES_EVENTOS.EVENTO_CREADO.mensaje,
+ evento: eventoCreado,
+ });
+ });
+});
diff --git a/_tests_/GrupoEmpleados/Controladores/crearGrupoEmpleados.controller.test.js b/_tests_/GrupoEmpleados/Controladores/crearGrupoEmpleados.controller.test.js
new file mode 100644
index 00000000..2636907c
--- /dev/null
+++ b/_tests_/GrupoEmpleados/Controladores/crearGrupoEmpleados.controller.test.js
@@ -0,0 +1,99 @@
+/**
+ * Mocks antes de importar el controlador
+ */
+jest.mock('@altertex/emp/repos/repositorioCrearGrupo', () => ({
+ crearGrupoYAsignarEmpleados: jest.fn(),
+ existeGrupoConNombre: jest.fn(),
+}));
+
+const repositorio = require('@altertex/emp/repos/repositorioCrearGrupo');
+const controlador = require('@altertex/emp/ctrl/crearGrupoEmpleados.controller');
+const MENSAJES = require('@altertex/util/const/mensajesEmpleados');
+
+describe('Controlador de Crear Grupo de Empleados', () => {
+ let req;
+ let res;
+
+ const datosMock = {
+ nombreGrupo: 'Grupo A',
+ descripcion: 'Descripción de prueba',
+ idCliente: 1,
+ listaEmpleados: [10, 20, 30],
+ };
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ req = {
+ body: { ...datosMock },
+ user: {
+ clienteSeleccionado: datosMock.idCliente,
+ },
+ };
+ res = {
+ status: jest.fn().mockReturnThis(),
+ json: jest.fn(),
+ };
+ });
+
+ test('Debe crear un grupo exitosamente', async () => {
+ const idGrupoMock = 999;
+
+ repositorio.existeGrupoConNombre.mockResolvedValue(false); // evitar conflicto de nombre repetido
+ repositorio.crearGrupoYAsignarEmpleados.mockResolvedValue({ idGrupo: idGrupoMock });
+
+ await controlador.crearGrupoEmpleados(req, res);
+
+ expect(repositorio.existeGrupoConNombre).toHaveBeenCalledWith(
+ datosMock.nombreGrupo,
+ datosMock.idCliente
+ );
+ expect(repositorio.crearGrupoYAsignarEmpleados).toHaveBeenCalledWith(
+ datosMock.nombreGrupo,
+ datosMock.descripcion,
+ datosMock.idCliente,
+ datosMock.listaEmpleados
+ );
+ expect(res.status).toHaveBeenCalledWith(201);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES.GRUPO_CREADO.mensaje,
+ idGrupo: idGrupoMock,
+ });
+ });
+
+ test('Debe manejar error por datos incompletos', async () => {
+ req.body = {}; // Datos faltantes
+ req.user = { clienteSeleccionado: 1 };
+
+ await controlador.crearGrupoEmpleados(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(400);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES.DATOS_INCOMPLETOS.mensaje,
+ });
+ expect(repositorio.crearGrupoYAsignarEmpleados).not.toHaveBeenCalled();
+ });
+
+ test('Debe manejar error interno del servidor', async () => {
+ repositorio.existeGrupoConNombre.mockResolvedValue(false);
+ repositorio.crearGrupoYAsignarEmpleados.mockRejectedValue(new Error('Fallo en DB'));
+
+ await controlador.crearGrupoEmpleados(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(500);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES.ERROR_CREAR_GRUPO.mensaje,
+ });
+ });
+
+ test('Debe manejar error de nombre duplicado', async () => {
+ repositorio.existeGrupoConNombre.mockResolvedValue(true); // nombre ya existe
+
+ await controlador.crearGrupoEmpleados(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(400);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES.GRUPO_NOMBRE_REPETIDO.mensaje,
+ });
+ expect(repositorio.crearGrupoYAsignarEmpleados).not.toHaveBeenCalled();
+ });
+});
\ No newline at end of file
diff --git a/_tests_/SetsProductos/actualizarSetsProductos.controller.test.js b/_tests_/SetsProductos/actualizarSetsProductos.controller.test.js
new file mode 100644
index 00000000..3aea3b8d
--- /dev/null
+++ b/_tests_/SetsProductos/actualizarSetsProductos.controller.test.js
@@ -0,0 +1,83 @@
+const request = require('supertest');
+const express = require('express');
+const bodyParser = require('body-parser');
+const MENSAJES = require('@altertex/util/const/mensajesSetsProductos');
+
+jest.mock('@altertex/setspro/repos/repositorioActualizarSetsProductos', () => ({
+ actualizarSetProductos: jest.fn()
+}));
+
+const repositorio = require('@altertex/setspro/repos/repositorioActualizarSetsProductos');
+const controller = require('@altertex/setspro/ctrl/actualizarSetsProductos.controller');
+
+const app = express();
+app.use(bodyParser.json());
+
+// 👇 Middleware para simular usuario con cliente seleccionado
+app.use((req, res, next) => {
+ req.user = { clienteSeleccionado: 1 };
+ next();
+});
+
+app.put('/sets-productos', controller.actualizarSetProductos);
+
+describe('Controlador actualizarSetProductos', () => {
+ // Silenciar console.error durante las pruebas para evitar ruido en la salida
+ beforeAll(() => {
+ jest.spyOn(console, 'error').mockImplementation(() => {});
+ });
+
+ // Restaurar el comportamiento original de console.error
+ afterAll(() => {
+ console.error.mockRestore();
+ });
+
+ // Limpia los mocks después de cada test
+ afterEach(() => jest.clearAllMocks());
+
+ it('debe devolver 400 si faltan campos requeridos', async () => {
+ const res = await request(app).put('/sets-productos').send({
+ nombre: 'Set incompleto'
+ });
+
+ expect(res.statusCode).toBe(MENSAJES.FORMATO_INVALIDO_DATOS.codigo);
+ expect(res.body.mensaje).toBe(MENSAJES.FORMATO_INVALIDO_DATOS.mensaje);
+ expect(res.body.detalles).toMatch(/nombre y lista de productos/i);
+ });
+
+ it('debe devolver 200 si la actualización es exitosa', async () => {
+ repositorio.actualizarSetProductos.mockResolvedValue();
+
+ const datos = {
+ idSetProducto: 1,
+ nombre: 'Set Actualizado',
+ descripcion: 'Nueva descripción',
+ activo: true,
+ productos: [101, 102]
+ };
+
+ const res = await request(app).put('/sets-productos').send(datos);
+
+ expect(res.statusCode).toBe(MENSAJES.SET_ACTUALIZADO.codigo);
+ expect(res.body.mensaje).toBe(MENSAJES.SET_ACTUALIZADO.mensaje);
+ expect(res.body.datos).toEqual(datos);
+ expect(repositorio.actualizarSetProductos).toHaveBeenCalledWith(1, datos);
+ });
+
+ it('debe devolver 500 si el repositorio lanza un error', async () => {
+ repositorio.actualizarSetProductos.mockRejectedValue(new Error('Fallo DB'));
+
+ const datos = {
+ idSetProducto: 2,
+ nombre: 'Set con error',
+ descripcion: 'desc',
+ activo: false,
+ productos: []
+ };
+
+ const res = await request(app).put('/sets-productos').send(datos);
+
+ expect(res.statusCode).toBe(MENSAJES.ERROR_ACTUALIZAR_SET.codigo);
+ expect(res.body.mensaje).toBe('Fallo DB');
+ });
+});
diff --git a/_tests_/SetsProductos/consultarListaSetsProductos.controller.test.js b/_tests_/SetsProductos/consultarListaSetsProductos.controller.test.js
new file mode 100644
index 00000000..3c4d609a
--- /dev/null
+++ b/_tests_/SetsProductos/consultarListaSetsProductos.controller.test.js
@@ -0,0 +1,81 @@
+// Mocks antes de importar el controlador
+jest.mock('@altertex/setspro/repos/repositorioConsultarSetsProductos', () => ({
+ obtenerSetsProductos: jest.fn(),
+}));
+
+// Importaciones
+const controlador = require('@altertex/setspro/ctrl/consultarSetsProductos.controller');
+const repositorio = require('@altertex/setspro/repos/repositorioConsultarSetsProductos');
+const MENSAJES = require('@altertex/util/const/mensajesSetsProductos');
+
+describe('Controlador consultarLista (sets de productos)', () => {
+ let req;
+ let res;
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+
+ req = {
+ user: {
+ clienteSeleccionado: '101',
+ },
+ };
+
+ res = {
+ status: jest.fn().mockReturnThis(),
+ json: jest.fn(),
+ };
+
+ jest.spyOn(console, 'error').mockImplementation(() => {}); // Silenciar errores
+ });
+
+ // Escenario 1: ID de cliente inválido
+ test('Debe retornar error si el ID del cliente no es válido', async () => {
+ req.user.clienteSeleccionado = undefined;
+
+ await controlador.consultarLista(req, res);
+ expect(res.status).toHaveBeenCalledWith(MENSAJES.PARAMETROS_INVALIDOS.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES.PARAMETROS_INVALIDOS.mensaje,
+ });
+ });
+
+ // Escenario 2: Lista de sets obtenida exitosamente
+ test('Debe retornar la lista de sets si la consulta es exitosa', async () => {
+ const mockSets = [
+ {
+ idSet: 1,
+ nombre: 'Set A',
+ productos: ['Producto 1', 'Producto 2'],
+ },
+ {
+ idSet: 2,
+ nombre: 'Set B',
+ productos: ['Producto 3'],
+ },
+ ];
+
+ repositorio.obtenerSetsProductos.mockResolvedValue(mockSets);
+
+ await controlador.consultarLista(req, res);
+
+ expect(repositorio.obtenerSetsProductos).toHaveBeenCalledWith(101);
+ expect(res.status).toHaveBeenCalledWith(MENSAJES.CONSULTA_EXITOSA.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES.CONSULTA_EXITOSA.mensaje,
+ setsProductos: mockSets,
+ });
+ });
+
+ // Escenario 3: Error inesperado en el repositorio
+ test('Debe manejar errores inesperados del repositorio', async () => {
+ repositorio.obtenerSetsProductos.mockRejectedValue(new Error('Error'));
+
+ await controlador.consultarLista(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES.ERROR_CONSULTAR_SETS_PRODUCTOS.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES.ERROR_CONSULTAR_SETS_PRODUCTOS.mensaje,
+ });
+ });
+});
diff --git a/_tests_/Usuarios/crearUsuario.controller.test.js b/_tests_/Usuarios/crearUsuario.controller.test.js
new file mode 100644
index 00000000..9e4496ed
--- /dev/null
+++ b/_tests_/Usuarios/crearUsuario.controller.test.js
@@ -0,0 +1,100 @@
+jest.mock('@altertex/usu/repos/repositorioCrearUsuario', () => ({
+ crearUsuarioConAsociaciones: jest.fn(),
+}));
+
+const repositorio = require('@altertex/usu/repos/repositorioCrearUsuario');
+const controlador = require('@altertex/usu/ctrl/crearUsuario.controller');
+const MENSAJES_USUARIOS = require('@altertex/util/const/mensajesUsuarios');
+
+describe('Controlador de Crear Usuario', () => {
+ let req;
+ let res;
+
+ const datosMock = {
+ nombreCompleto: 'María López',
+ correoElectronico: 'maria@correo.com',
+ contrasenia: 'Contrasenia1.',
+ numeroTelefono: '5512345678',
+ direccion: 'Calle Falsa 123',
+ fechaNacimiento: '1990-01-01',
+ genero: 'Femenino',
+ estatus: true,
+ idRol: 2,
+ idCliente: [1],
+ };
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ req = { body: { ...datosMock } };
+ res = {
+ status: jest.fn().mockReturnThis(),
+ json: jest.fn(),
+ };
+ });
+
+ test('Debe crear un usuario exitosamente', async () => {
+ repositorio.crearUsuarioConAsociaciones.mockResolvedValue({ idUsuario: 101 });
+
+ await controlador.crearUsuario(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_USUARIOS.USUARIO_CREADO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_USUARIOS.USUARIO_CREADO.mensaje,
+ idUsuario: 101,
+ });
+ expect(repositorio.crearUsuarioConAsociaciones).toHaveBeenCalled();
+ });
+
+ test('Debe rechazar si faltan campos requeridos', async () => {
+ req.body = { ...datosMock, nombreCompleto: undefined };
+
+ await controlador.crearUsuario(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(400);
+ expect(res.json).toHaveBeenCalledWith({ mensaje: 'Faltan campos requeridos' });
+ });
+
+ test('Debe rechazar correo inválido', async () => {
+ req.body.correoElectronico = 'correo-no-valido';
+
+ await controlador.crearUsuario(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_USUARIOS.CORREO_INVALIDO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_USUARIOS.CORREO_INVALIDO.mensaje,
+ });
+ });
+
+ test('Debe rechazar contraseña débil (sin mayúscula)', async () => {
+ req.body.contrasenia = 'contrasenia$1';
+
+ await controlador.crearUsuario(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_USUARIOS.CONTRASENA_DEBIL.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: 'La contraseña debe contener al menos una letra mayúscula.',
+ });
+ });
+
+ test('Debe rechazar número telefónico inválido', async () => {
+ req.body.numeroTelefono = 'abc123';
+
+ await controlador.crearUsuario(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_USUARIOS.TELEFONO_INVALIDO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_USUARIOS.TELEFONO_INVALIDO.mensaje,
+ });
+ });
+
+ test('Debe manejar error del repositorio', async () => {
+ repositorio.crearUsuarioConAsociaciones.mockRejectedValue(new Error('Fallo'));
+
+ await controlador.crearUsuario(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_USUARIOS.ERROR_CREAR_USUARIO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_USUARIOS.ERROR_CREAR_USUARIO.mensaje,
+ });
+ });
+});
diff --git a/_tests_/autenticacion/Controladores/inicioSesion.controller.test.js b/_tests_/autenticacion/Controladores/inicioSesion.controller.test.js
new file mode 100644
index 00000000..f66cca03
--- /dev/null
+++ b/_tests_/autenticacion/Controladores/inicioSesion.controller.test.js
@@ -0,0 +1,192 @@
+/**
+ *
+ * RF78 - Iniciar Sesion - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF78
+ *
+ * Primero configuramos los mocks antes de importar el controlador
+ */
+jest.mock('@altertex/aut/repos/repositorioInicioSesion', () => ({
+ obtenerUsuario: jest.fn(),
+}));
+jest.mock('bcryptjs', () => ({
+ compare: jest.fn(),
+}));
+jest.mock('jsonwebtoken', () => ({
+ sign: jest.fn(),
+}));
+
+// Mock del módulo de mensajes con los valores reales
+jest.mock('@altertex/util/const/mensajesAutenticacion', () => ({
+ INICIO_SESION_EXITOSO: {
+ codigo: 200,
+ mensaje: 'Inicio de sesión exitoso.',
+ },
+ CAMPOS_OBLIGATORIOS: {
+ codigo: 400,
+ mensaje: 'Se necesita ingresar correo y contraseña.',
+ },
+ FORMATO_CORREO_INVALIDO: {
+ codigo: 400,
+ mensaje: 'El formato del correo electrónico no es válido.',
+ },
+ CREDENCIALES_INVALIDAS: {
+ codigo: 401,
+ mensaje: 'Usuario o contraseña incorrectos.',
+ },
+ ERROR_SERVIDOR: {
+ codigo: 500,
+ mensaje: 'Ocurrió un error inesperado. Intente de nuevo más tarde.',
+ },
+}));
+
+// Importamos los módulos después de configurar los mocks
+const controladorInicioSesion = require('@altertex/aut/ctrl/inicioSesion.controller');
+const repositorio = require('@altertex/aut/repos/repositorioInicioSesion');
+const bcrypt = require('bcryptjs');
+const jwt = require('jsonwebtoken');
+const MENSAJES_AUTENTICACION = require('@altertex/util/const/mensajesAutenticacion');
+
+// Mock para process.env
+process.env.JWT_SECRET = 'secret_test_key';
+
+describe('Controlador de Inicio de Sesión', () => {
+ let req;
+ let res;
+
+ beforeEach(() => {
+ // Reset de los mocks
+ jest.clearAllMocks();
+
+ // Mock de req y res
+ req = {
+ body: {},
+ };
+
+ res = {
+ status: jest.fn().mockReturnThis(),
+ json: jest.fn(),
+ cookie: jest.fn(),
+ };
+ });
+
+ test('Debe retornar error 400 cuando faltan campos requeridos', async () => {
+ // Arrange
+ req.body = { correo: '', contrasenia: '' };
+
+ // Act
+ await controladorInicioSesion.inicioSesion(req, res);
+
+ // Assert
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_AUTENTICACION.CAMPOS_OBLIGATORIOS.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_AUTENTICACION.CAMPOS_OBLIGATORIOS.mensaje,
+ });
+ });
+
+ test('Debe retornar error 400 cuando el formato de correo es inválido', async () => {
+ // Arrange
+ req.body = { correo: 'correo-invalido', contrasenia: 'password123' };
+
+ // Act
+ await controladorInicioSesion.inicioSesion(req, res);
+
+ // Assert
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_AUTENTICACION.FORMATO_CORREO_INVALIDO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_AUTENTICACION.FORMATO_CORREO_INVALIDO.mensaje,
+ });
+ });
+
+ test('Debe retornar error 401 cuando el usuario no existe', async () => {
+ // Arrange
+ req.body = { correo: 'usuario@ejemplo.com', contrasenia: 'password123' };
+
+ repositorio.obtenerUsuario.mockResolvedValue({
+ infoUsuario: [],
+ permisos: [],
+ clientesAsociados: [],
+ });
+
+ // Act
+ await controladorInicioSesion.inicioSesion(req, res);
+
+ // Assert
+ expect(repositorio.obtenerUsuario).toHaveBeenCalledWith('usuario@ejemplo.com');
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_AUTENTICACION.CREDENCIALES_INVALIDAS.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_AUTENTICACION.CREDENCIALES_INVALIDAS.mensaje,
+ });
+ });
+
+ test('Debe retornar error 401 cuando la contraseña es incorrecta', async () => {
+ // Arrange
+ req.body = { correo: 'usuario@ejemplo.com', contrasenia: 'password123' };
+
+ repositorio.obtenerUsuario.mockResolvedValue({
+ infoUsuario: [
+ {
+ correoElectronico: 'usuario@ejemplo.com',
+ contrasenia: 'hashed_password',
+ },
+ ],
+ permisos: [],
+ clientesAsociados: [],
+ });
+
+ bcrypt.compare.mockResolvedValue(false);
+
+ // Act
+ await controladorInicioSesion.inicioSesion(req, res);
+
+ // Assert
+ expect(bcrypt.compare).toHaveBeenCalledWith('password123', 'hashed_password');
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_AUTENTICACION.CREDENCIALES_INVALIDAS.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_AUTENTICACION.CREDENCIALES_INVALIDAS.mensaje,
+ });
+ });
+
+ test('Debe retornar status 200 y generar token cuando las credenciales son correctas', async () => {
+ // Arrange
+ req.body = { correo: 'usuario@ejemplo.com', contrasenia: 'password123' };
+ const mockUsuario = {
+ correoElectronico: 'usuario@ejemplo.com',
+ contrasenia: 'hashed_password',
+ };
+ const mockPermisos = ['permiso1', 'permiso2'];
+ const mockClientesAsociados = [1, 2, 3];
+
+ repositorio.obtenerUsuario.mockResolvedValue({
+ infoUsuario: [mockUsuario],
+ permisos: mockPermisos,
+ clientesAsociados: mockClientesAsociados,
+ });
+
+ bcrypt.compare.mockResolvedValue(true);
+ jwt.sign.mockReturnValue('token_jwt_generado');
+
+ // Act
+ await controladorInicioSesion.inicioSesion(req, res);
+
+ // Assert
+ expect(jwt.sign).toHaveBeenCalledWith(
+ {
+ correo: 'usuario@ejemplo.com',
+ permisos: mockPermisos,
+ clientesAsociados: mockClientesAsociados,
+ },
+ 'secret_test_key',
+ { expiresIn: '8h' }
+ );
+
+ expect(res.cookie).toHaveBeenCalledWith('token', 'token_jwt_generado', {
+ httpOnly: true,
+ secure: true,
+ sameSite: 'None',
+ });
+
+ expect(res.status).toHaveBeenCalledWith(MENSAJES_AUTENTICACION.INICIO_SESION_EXITOSO.codigo);
+ expect(res.json).toHaveBeenCalledWith({
+ mensaje: MENSAJES_AUTENTICACION.INICIO_SESION_EXITOSO.mensaje,
+ });
+ });
+});
diff --git a/_tests_/autenticacion/Repositorios/repositorioInicioSesion.test.js b/_tests_/autenticacion/Repositorios/repositorioInicioSesion.test.js
new file mode 100644
index 00000000..433b892d
--- /dev/null
+++ b/_tests_/autenticacion/Repositorios/repositorioInicioSesion.test.js
@@ -0,0 +1,91 @@
+/**
+ * RF78 - Iniciar Sesion - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF78
+ *
+ * Primero configuramos los mocks
+ */
+jest.mock("@altertex/util/ser/correrQuery", () => jest.fn());
+
+jest.mock("@altertex/util/const/consultasUsuarios", () => ({
+ OBTENER_USUARIO: "SELECT * FROM usuarios WHERE correoElectronico = ?",
+ OBTENER_PERMISOS: "SELECT nombre FROM permisos WHERE correoElectronico = ?",
+ OBTENER_CLIENTES_ASOCIADOS:
+ "SELECT idCliente FROM clientes_usuarios WHERE correoElectronico = ?",
+}));
+
+// Importamos después de configurar los mocks
+const repositorio = require("@altertex/aut/repos/repositorioInicioSesion");
+const correrQuery = require("@altertex/util/ser/correrQuery");
+const CONSULTAS_USUARIOS = require("@altertex/util/const/consultasUsuarios");
+
+describe("Repositorio de Inicio de Sesión", () => {
+ beforeEach(() => {
+ // Limpiar los mocks antes de cada prueba
+ jest.clearAllMocks();
+ });
+
+ test("obtenerUsuario debe retornar información del usuario, permisos y clientes asociados", async () => {
+ // Arrange
+ const correoElectronico = "usuario@ejemplo.com";
+ const mockUsuario = [
+ {
+ id: 1,
+ nombre: "Usuario Test",
+ correoElectronico,
+ contrasenia: "hashed_password",
+ },
+ ];
+ const mockPermisos = [{ nombre: "admin" }, { nombre: "usuario" }];
+ const mockClientesAsociados = [{ idCliente: 1 }, { idCliente: 2 }];
+
+ // Configuramos el comportamiento del mock para cada llamada
+ correrQuery
+ .mockResolvedValueOnce(mockUsuario)
+ .mockResolvedValueOnce(mockPermisos)
+ .mockResolvedValueOnce(mockClientesAsociados);
+
+ // Act
+ const resultado = await repositorio.obtenerUsuario(correoElectronico);
+
+ // Assert
+ expect(correrQuery).toHaveBeenCalledTimes(3);
+ expect(correrQuery).toHaveBeenNthCalledWith(
+ 1,
+ CONSULTAS_USUARIOS.OBTENER_USUARIO,
+ [correoElectronico]
+ );
+ expect(correrQuery).toHaveBeenNthCalledWith(
+ 2,
+ CONSULTAS_USUARIOS.OBTENER_PERMISOS,
+ [correoElectronico]
+ );
+ expect(correrQuery).toHaveBeenNthCalledWith(
+ 3,
+ CONSULTAS_USUARIOS.OBTENER_CLIENTES_ASOCIADOS,
+ [correoElectronico]
+ );
+
+ expect(resultado).toEqual({
+ infoUsuario: mockUsuario,
+ permisos: ["admin", "usuario"],
+ clientesAsociados: [1, 2],
+ });
+ });
+
+ test("obtenerUsuario debe manejar errores correctamente", async () => {
+ // Arrange
+ const correoElectronico = "usuario@ejemplo.com";
+ const errorMessage = "Error en la base de datos";
+
+ correrQuery.mockRejectedValue(new Error(errorMessage));
+
+ // Act
+ const resultado = await repositorio.obtenerUsuario(correoElectronico);
+
+ // Assert
+ expect(correrQuery).toHaveBeenCalledWith(
+ CONSULTAS_USUARIOS.OBTENER_USUARIO,
+ [correoElectronico]
+ );
+ expect(resultado).toBe(`Error obteniendo usuario`);
+ });
+});
diff --git a/app.js b/app.js
index e77687f7..c2ded97d 100644
--- a/app.js
+++ b/app.js
@@ -1,38 +1,89 @@
-const dotenv = require("dotenv");
-const envFile = `.env.${process.env.NODE_ENV || "staging"}`; // Defaults to 'development' if NODE_ENV is not set
-dotenv.config({ path: envFile });
+require('module-alias/register');
+require('@altertex/config/dotenv');
-const cors = require("cors");
-const express = require("express");
-const cookieParser = require("cookie-parser");
-const revisarApiKey = require("./util/middlewares/revisarApiKey");
+//Importaciones de librerias
+const express = require('express');
+const cors = require('cors');
+const cookieParser = require('cookie-parser');
+const swaggerJSDoc = require('swagger-jsdoc');
+const csrf = require('csurf')
-const app = express();
+//Importaciones de configuracion
+const corsOptions = require('@altertex/config/corsOptions');
+const opcionesSwagger = require('@altertex/config/swagger');
+const swaggerUI = require('swagger-ui-express');
-app.use(express.json());
+//Importaciones de rutas
+const rutasAutenticacion = require('@altertex/aut/rutas/indexAutenticacion.routes');
+const rutasUsuarios = require('@altertex/usu/rutas/indexUsuarios.routes');
+const rutasCategorias = require('@altertex/cat/rutas/indexCategorias.routes');
+const rutasProductos = require('@altertex/pro/rutas/indexProductos.routes');
+const rutasProveedores = require('@altertex/prove/rutas/indexProveedores.routes');
+const rutasSetsProductos = require('@altertex/setspro/rutas/indexSetsProductos.routes');
+const rutasEmpleados = require('@altertex/emp/rutas/indexEmpleados.routes');
+const rutasClientes = require('@altertex/cli/rutas/indexClientes.routes');
+const rutasRoles = require('@altertex/rol/rutas/indexRoles.routes');
+const rutasCuotas = require('@altertex/cuota/rutas/indexCuotas.routes');
+const rutasPedidos = require('@altertex/pedidos/rutas/indexPedidos.routes');
+const rutasEventos = require('@altertex/eve/rutas/indexEventos.routes');
+const rutasPagos = require('@altertex/pago/rutas/indexPagos.routes');
+const RUTAS = require('@altertex/util/const/rutas');
-app.use(
- cors({
- origin: [process.env.LOCAL_URL, process.env.DEPLOYED_URL],
- methods: ["GET", "POST", "PUT", "DELETE"],
- credentials: true, // ✅ Allow cookies
- })
-);
+//Importaciones de CRON jobs
+const cronCuotas = require('@altertex/CRON/ctrl/actualizarCuotaSet.controller');
-app.use(revisarApiKey("x-api-key", "Api key invalida"));
+const puerto = process.env.PORT || 5000;
+//Configuracion de aplicacion express
+const app = express();
+app.use(express.json({limit: '5mb'}));
+app.use(express.urlencoded({limit: '5mb', extended: true}));
app.use(cookieParser());
+app.use(cors(corsOptions));
+const proteccionCsrf = csrf({
+ cookie: {
+ httpOnly: true,
+ secure: false,
+ sameSite: 'strict'
+ }
+})
+
+cronCuotas.start();
-const ambiente = process.env.NODE_ENV;
+//Usar las rutas para que esten disponibles en la aplicacion
+app.use(RUTAS.API, rutasAutenticacion);
+app.use(RUTAS.API, rutasUsuarios);
+app.use(RUTAS.API, rutasProductos);
+app.use(RUTAS.API, rutasProveedores);
+app.use(RUTAS.API, rutasSetsProductos);
+app.use(RUTAS.API, rutasEmpleados);
+app.use(RUTAS.API, rutasClientes);
+app.use(RUTAS.API, rutasRoles);
+app.use(RUTAS.API, rutasCuotas);
+app.use(RUTAS.API, rutasCategorias);
+app.use(RUTAS.API, rutasPedidos);
+app.use(RUTAS.API, rutasEventos);
+app.use(RUTAS.API, rutasPagos);
-app.get("/", async (req, res) => {
- res.status(201).json({ message: `Proyecto TEXT&LINES ${ambiente}` });
+app.use((req, res, next) => {
+ if (req.method === 'GET' && req.path === '/api/csrf-token') {
+ return next()
+ }
+ proteccionCsrf(req, res, next)
+})
+
+app.get('/api/csrf-token', proteccionCsrf, (req, res) => {
+ res.json({csrfToken: req.csrfToken()});
});
-const port = process.env.PORT || 5000;
+app.get('/', async (req, res) => {
+ return res
+ .status(200)
+ .json({mensaje: `Ruta por default Proyecto Text&Lines en ambiente: ${process.env.NODE_ENV}`});
+});
-app.listen(port, () =>
- console.log(
- `Server corriendo en puerto: ${port} ${port} en ambiente de ${process.env.NODE_ENV}.`
- )
-);
+//Configuracion de swaggerUI
+const swaggerSpec = swaggerJSDoc(opcionesSwagger);
+app.use(RUTAS.API_DOCS, swaggerUI.serve, swaggerUI.setup(swaggerSpec));
+app.listen(puerto, () =>
+ console.log(`Servidor corriendo en puerto ${puerto} [${process.env.NODE_ENV}]`));
diff --git a/dump.rdb b/dump.rdb
new file mode 100644
index 00000000..fa5c9e72
Binary files /dev/null and b/dump.rdb differ
diff --git a/ecosystem-production.config.js b/ecosystem-production.config.js
new file mode 100644
index 00000000..a83e4fee
--- /dev/null
+++ b/ecosystem-production.config.js
@@ -0,0 +1,15 @@
+module.exports = {
+ apps: [
+ {
+ name: 'app-production',
+ script: './app.js',
+ instances: 'max',
+ exec_mode: 'cluster',
+ watch: false,
+ env: {
+ NODE_ENV: 'production',
+ PORT: 3000,
+ },
+ },
+ ],
+};
diff --git a/ecosystem-staging.config.js b/ecosystem-staging.config.js
new file mode 100644
index 00000000..9bbc443c
--- /dev/null
+++ b/ecosystem-staging.config.js
@@ -0,0 +1,15 @@
+module.exports = {
+ apps: [
+ {
+ name: 'app-staging',
+ script: './app.js',
+ instances: 'max',
+ exec_mode: 'cluster',
+ watch: false,
+ env: {
+ NODE_ENV: 'staging',
+ PORT: 4000,
+ },
+ },
+ ],
+};
diff --git a/ecosystem.config.js b/ecosystem.config.js
deleted file mode 100644
index 75dcd038..00000000
--- a/ecosystem.config.js
+++ /dev/null
@@ -1,26 +0,0 @@
-module.exports = {
- apps: [
- {
- name: "app-production", // Name of your app
- script: "./app.js", // Path to your entry file (e.g., app.js, server.js, etc.)
- instances: "max", // Run maximum instances of your app based on available CPU cores
- exec_mode: "cluster", // Use cluster mode for load balancing (optional)
- watch: false, // Disable file watching (set to true if you want PM2 to restart on file changes)
- env: {
- NODE_ENV: "production", // Set the environment variable to "production"
- PORT: 3000,
- },
- },
- {
- name: "app-staging", // Name of your app
- script: "./app.js", // Path to your entry file (e.g., app.js, server.js, etc.)
- instances: "max", // Run maximum instances of your app based on available CPU cores
- exec_mode: "cluster", // Use cluster mode for load balancing (optional)
- watch: false, // Disable file watching (set to true if you want PM2 to restart on file changes)
- env: {
- NODE_ENV: "staging", // Set environment variable for production explicitly (optional)
- PORT: 4000, // Define the port your app runs on (optional)
- },
- },
- ],
-};
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 3d5fe7eb..ebc27158 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,67 +1,139 @@
-import js from "@eslint/js";
-import globals from "globals";
+import js from '@eslint/js';
+import globals from 'globals';
+import jsdoc from 'eslint-plugin-jsdoc';
export default [
- { ignores: ["dist", "node_modules"] },
+ { ignores: ['dist', 'node_modules'] },
+
+ // JSDoc rules for target files - controllers and utility/data folders (excluding Constantes)
{
- files: ["**/*.{js,mjs,cjs}"],
+ plugins: {
+ jsdoc,
+ },
+ files: ['**/Utilidades/**/*.js', '**/Datos/**/*.js', '**/*.controller.js'],
+ ignores: [
+ '**/Utilidades/**/Constantes/**/*.js', // Exclude Constantes folders
+ ],
languageOptions: {
- ecmaVersion: "latest",
- globals: globals.node, // Set Node.js globals
+ ecmaVersion: 'latest',
+ globals: globals.node,
parserOptions: {
ecmaFeatures: { jsx: false },
- sourceType: "module",
+ sourceType: 'module',
+ },
+ },
+ settings: {
+ jsdoc: {
+ mode: 'jsdoc', // Classic JS mode, not TypeScript
},
},
rules: {
- ...js.configs.recommended.rules,
+ // Enforce JSDoc presence - Highest priority
+ 'jsdoc/require-jsdoc': [
+ 'error', // Changed from "warn" to "error" to enforce more strictly
+ {
+ require: {
+ FunctionDeclaration: true,
+ MethodDefinition: true,
+ ClassDeclaration: true,
+ ArrowFunctionExpression: true, // Changed to true to require JSDoc for arrow functions
+ FunctionExpression: true, // Changed to true to require JSDoc for function expressions
+ },
+ exemptEmptyFunctions: false, // Require JSDoc even for empty functions
+ },
+ ],
+
+ // Enforce JSDoc content quality - With warnings
+ 'jsdoc/require-param': 'error',
+ 'jsdoc/require-param-name': 'error',
+ 'jsdoc/require-param-type': 'error',
+ 'jsdoc/require-returns': 'error',
+ 'jsdoc/require-returns-type': 'error',
+ 'jsdoc/valid-types': 'error',
+ 'jsdoc/check-param-names': 'error',
+ 'jsdoc/check-tag-names': 'error',
+ 'jsdoc/check-types': 'error',
- // ESLint Rules for Backend
- "object-shorthand": "error",
- "no-new-object": "error",
- "default-param-last": "error",
- "no-new-func": "error",
- "function-paren-newline": ["error", "consistent"],
- "no-duplicate-imports": "error",
- "object-curly-newline": ["error", { consistent: true }],
- "no-undef": "error",
- "prefer-const": "error",
- "one-var": ["error", "never"],
- "no-multi-assign": "error",
- "no-plusplus": "error",
- "operator-linebreak": ["error", "before"],
- "new-cap": [
- "error",
+ // Optional rules based on your preference
+ 'jsdoc/require-description': 'warn', // Added: Require general descriptions
+ 'jsdoc/require-param-description': 'off', // Kept off as per your preference
+ 'jsdoc/require-returns-description': 'off', // Kept off as per your preference
+ },
+ },
+
+ // General rules for all JavaScript files
+ {
+ files: ['**/*.{js,mjs,cjs}'],
+ languageOptions: {
+ ecmaVersion: 'latest',
+ globals: globals.node,
+ parserOptions: {
+ ecmaFeatures: { jsx: false },
+ sourceType: 'module',
+ },
+ },
+ rules: {
+ ...js.configs.recommended.rules,
+ 'object-shorthand': 'error',
+ 'no-new-object': 'error',
+ 'default-param-last': 'error',
+ 'no-new-func': 'error',
+ 'function-paren-newline': ['error', 'consistent'],
+ 'no-duplicate-imports': 'error',
+ 'object-curly-newline': ['error', { consistent: true }],
+ 'no-undef': 'error',
+ 'prefer-const': 'error',
+ 'one-var': ['error', 'never'],
+ 'no-multi-assign': 'error',
+ 'no-plusplus': 'error',
+ 'operator-linebreak': ['error', 'before'],
+ 'new-cap': [
+ 'error',
{
- newIsCap: true, // Enforce capitalization for constructors
- capIsNew: false, // Allow capitalized functions that aren't constructors
- capIsNewExceptions: ["Router"], // Allow express.Router() without error
+ newIsCap: true,
+ capIsNew: false,
+ capIsNewExceptions: ['Router'],
properties: false,
},
],
camelcase: [
- "error",
+ 'error',
{
- properties: "never", // Ignore object properties
- allow: ["exec_mode"], // Allow specific exceptions
+ properties: 'never',
+ allow: ['exec_mode'],
},
],
- "id-length": ["error", { min: 2 }],
- "nonblock-statement-body-position": ["error", "beside"],
- "brace-style": ["error", "1tbs", { allowSingleLine: true }],
- "no-iterator": "error",
- "no-restricted-syntax": "error",
- "prefer-arrow-callback": "error",
- "arrow-spacing": "error",
- "no-array-constructor": "error",
- "template-curly-spacing": ["error", "never"],
- "prefer-template": "error",
- "no-eval": "error",
- "no-useless-constructor": "error",
- "no-dupe-class-members": "error",
- "class-methods-use-this": "error",
- "dot-notation": "error",
- "prefer-exponentiation-operator": "error",
+ 'id-length': ['error', { min: 2 }],
+ 'nonblock-statement-body-position': ['error', 'beside'],
+ 'brace-style': ['error', '1tbs', { allowSingleLine: true }],
+ 'no-iterator': 'error',
+ 'no-restricted-syntax': 'error',
+ 'prefer-arrow-callback': 'error',
+ 'arrow-spacing': 'error',
+ 'no-array-constructor': 'error',
+ 'template-curly-spacing': ['error', 'never'],
+ 'prefer-template': 'error',
+ 'no-eval': 'error',
+ 'no-useless-constructor': 'error',
+ 'no-dupe-class-members': 'error',
+ 'class-methods-use-this': 'error',
+ 'dot-notation': 'error',
+ 'prefer-exponentiation-operator': 'error',
+ },
+ },
+
+ // Special configuration for test files
+ {
+ files: ['**/*.test.js', '**/*.spec.js', 'jest.setup.js'],
+ languageOptions: {
+ ecmaVersion: 'latest',
+ globals: {
+ ...globals.node,
+ ...globals.jest,
+ },
+ parserOptions: {
+ sourceType: 'module',
+ },
},
},
];
diff --git a/jest.config.js b/jest.config.js
new file mode 100644
index 00000000..9162afb7
--- /dev/null
+++ b/jest.config.js
@@ -0,0 +1,103 @@
+module.exports = {
+ // La raíz del directorio que Jest usará para buscar los archivos
+ rootDir: '.',
+
+ // Rutas a directorios que Jest debe ignorar durante las pruebas
+ testPathIgnorePatterns: ['/node_modules/'],
+
+ // Patrón para encontrar archivos de prueba
+ testMatch: ['**/__tests__/**/*.js', '**/?(*.)+(spec|test).js'],
+
+ // Entorno de prueba
+ testEnvironment: 'node',
+
+ // Cobertura de código
+ collectCoverage: true,
+ coverageDirectory: 'coverage',
+
+ // Módulos que deben ser transformados
+ // (Si usas babel o typescript necesitarías configurar esto)
+ transform: {},
+ moduleFileExtensions: ['js', 'json'],
+ moduleNameMapper: {
+ '^@altertex/root(.*)$': '$1',
+
+ // Autenticacion module mappings
+ '^@altertex/aut/ctrl/(.*)$': '/Autenticacion/Controladores/$1',
+ '^@altertex/aut/repos/(.*)$': '/Autenticacion/Datos/Repositorios/$1',
+ '^@altertex/aut/rutasInd/(.*)$': '/Autenticacion/Rutas/RutasIndividuales/$1',
+ '^@altertex/aut/rutas/(.*)$': '/Autenticacion/Rutas/$1',
+ '^@altertex/aut/datos/(.*)$': '/Autenticacion/Datos/$1',
+ '^@altertex/aut/(.*)$': '/Autenticacion/$1',
+
+ // Categorias module mappings
+ "^@altertex/cat/ctrl/(.*)$": "/Categorias/Controladores/$1",
+ "^@altertex/cat/repos/(.*)$": "/Categorias/Datos/Repositorios/$1",
+ "^@altertex/cat/rutasInd/(.*)$": "/Categorias/Rutas/RutasIndividuales/$1",
+ "^@altertex/cat/rutas/(.*)$": "/Categorias/Rutas/$1",
+ "^@altertex/cat/datos/(.*)$": "/Categorias/Datos/$1",
+ "^@altertex/cat/(.*)$": "/Categorias/$1",
+
+ // Clientes module mappings
+ "^@altertex/cli/ctrl/(.*)$": "/Clientes/Controladores/$1",
+ "^@altertex/cli/repos/(.*)$": "/Clientes/Datos/Repositorios/$1",
+ "^@altertex/cli/rutasInd/(.*)$": "/Clientes/Rutas/RutasIndividuales/$1",
+ "^@altertex/cli/rutas/(.*)$": "/Clientes/Rutas/$1",
+ "^@altertex/cli/datos/(.*)$": "/Clientes/Datos/$1",
+ "^@altertex/cli/(.*)$": "/Clientes/$1",
+
+ // Cuotas module mappings (added)
+ '^@altertex/cuota/ctrl/(.*)$': '/Cuotas/Controladores/$1',
+ '^@altertex/cuota/repos/(.*)$': '/Cuotas/Datos/Repositorios/$1',
+ '^@altertex/cuota/rutasInd/(.*)$': '/Cuotas/Rutas/RutasIndividuales/$1',
+ '^@altertex/cuota/rutas/(.*)$': '/Cuotas/Rutas/$1',
+ '^@altertex/cuota/datos/(.*)$': '/Cuotas/Datos/$1',
+ '^@altertex/cuota/(.*)$': '/Cuotas/$1',
+
+ // CRON jobs module mappings (added)
+ '^@altertex/CRON/ctrl/(.*)$': '/CRON_JOBS/Controladores/$1',
+ '^@altertex/CRON/datos/(.*)$': '/CRON_JOBS/Datos/$1',
+ '^@altertex/CRON/repos/(.*)$': '/CRON_JOBS/Datos/Repositorios/$1',
+ '^@altertex/CRON/(.*)$': '/CRON_JOBS/$1',
+
+ // Configuration and utilities mappings
+ '^@altertex/config/(.*)$': '/Configuracion/$1',
+ '^@altertex/util/ser/(.*)$': '/Utilidades/Servicios/$1',
+ '^@altertex/util/inter/(.*)$': '/Utilidades/Intermediarios/$1',
+ '^@altertex/util/const/(.*)$': '/Utilidades/Constantes/$1',
+ '^@altertex/util/bd/(.*)$': '/Utilidades/BaseDeDatos/$1',
+ '^@altertex/util/(.*)$': '/Utilidades/$1',
+
+ // GrupoEmpleados module mappings
+ "^@altertex/emp/ctrl/(.*)$": "/Empleados/Controladores/$1",
+ "^@altertex/emp/repos/(.*)$": "/Empleados/Datos/Repositorios/$1",
+ "^@altertex/emp/rutasInd/(.*)$": "/Empleados/Rutas/RutasIndividuales/$1",
+ "^@altertex/emp/rutas/(.*)$": "/Empleados/Rutas/$1",
+ "^@altertex/emp/datos/(.*)$": "/Empleados/Datos/$1",
+ "^@altertex/emp/(.*)$": "/Empleados/$1",
+
+ // Eventos module mappings
+ "^@altertex/eve/ctrl/(.*)$": "/Eventos/Controladores/$1",
+ "^@altertex/eve/repos/(.*)$": "/Eventos/Datos/Repositorios/$1",
+ "^@altertex/eve/rutasInd/(.*)$": "/Eventos/Rutas/RutasIndividuales/$1",
+ "^@altertex/eve/rutas/(.*)$": "/Eventos/Rutas/$1",
+ "^@altertex/eve/datos/(.*)$": "/Eventos/Datos/$1",
+ "^@altertex/eve/(.*)$": "/Eventos/$1",
+
+ // Usuarios module mappings
+ '^@altertex/usu/ctrl/(.*)$': '/Usuarios/Controladores/$1',
+ '^@altertex/usu/repos/(.*)$': '/Usuarios/Datos/Repositorios/$1',
+ '^@altertex/usu/rutasInd/(.*)$': '/Usuarios/Rutas/RutasIndividuales/$1',
+ '^@altertex/usu/rutas/(.*)$': '/Usuarios/Rutas/$1',
+ '^@altertex/usu/datos/(.*)$': '/Usuarios/Datos/$1',
+ '^@altertex/usu/(.*)$': '/Usuarios/$1',
+
+ // Sets de productos
+ "^@altertex/setspro/ctrl/(.*)$": "/SetsProductos/Controladores/$1",
+ "^@altertex/setspro/repos/(.*)$": "/SetsProductos/Datos/Repositorios/$1",
+
+ // Generic mapping as fallback
+ '^@altertex/(.*)$': '/$1',
+
+ },
+};
diff --git a/jest.setup.js b/jest.setup.js
new file mode 100644
index 00000000..0fb8877d
--- /dev/null
+++ b/jest.setup.js
@@ -0,0 +1,2 @@
+// Configuración global para Jest
+jest.setTimeout(10000); // Timeout de 10 segundos para las pruebas
diff --git a/jsconfig.json b/jsconfig.json
new file mode 100644
index 00000000..9e8820a1
--- /dev/null
+++ b/jsconfig.json
@@ -0,0 +1,97 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@altertex/*": ["./*"],
+ "@altertex/aut/*": ["Autenticacion/*"],
+ "@altertex/aut/ctrl/*": ["Autenticacion/Controladores/*"],
+ "@altertex/aut/datos/*": ["Autenticacion/Datos/*"],
+ "@altertex/aut/repos/*": ["Autenticacion/Datos/Repositorios/*"],
+ "@altertex/aut/rutas/*": ["Autenticacion/Rutas/*"],
+ "@altertex/aut/rutasInd/*": ["Autenticacion/Rutas/RutasIndividuales/*"],
+ "@altertex/usu/*": ["Usuarios/*"],
+ "@altertex/usu/ctrl/*": ["Usuarios/Controladores/*"],
+ "@altertex/usu/datos/*": ["Usuarios/Datos/*"],
+ "@altertex/usu/repos/*": ["Usuarios/Datos/Repositorios/*"],
+ "@altertex/usu/rutas/*": ["Usuarios/Rutas/*"],
+ "@altertex/usu/rutasInd/*": ["Usuarios/Rutas/RutasIndividuales/*"],
+ "@altertex/emp/*": ["Empleados/*"],
+ "@altertex/emp/ctrl/*": ["Empleados/Controladores/*"],
+ "@altertex/emp/datos/*": ["Empleados/Datos/*"],
+ "@altertex/emp/repos/*": ["Empleados/Datos/Repositorios/*"],
+ "@altertex/emp/rutas/*": ["Empleados/Rutas/*"],
+ "@altertex/emp/rutasInd/*": ["Empleados/Rutas/RutasIndividuales/*"],
+ "@altertex/cli/*": ["Clientes/*"],
+ "@altertex/cli/ctrl/*": ["Clientes/Controladores/*"],
+ "@altertex/cli/datos/*": ["Clientes/Datos/*"],
+ "@altertex/cli/repos/*": ["Clientes/Datos/Repositorios/*"],
+ "@altertex/cli/rutas/*": ["Clientes/Rutas/*"],
+ "@altertex/cli/rutasInd/*": ["Clientes/Rutas/RutasIndividuales/*"],
+ "@altertex/config/*": ["Configuracion/*"],
+ "@altertex/util/*": ["Utilidades/*"],
+ "@altertex/util/bd/*": ["Utilidades/BaseDeDatos/*"],
+ "@altertex/util/const/*": ["Utilidades/Constantes/*"],
+ "@altertex/util/inter/*": ["Utilidades/Intermediarios/*"],
+ "@altertex/util/vali/*": ["Utilidades/Intermediarios/Validaciones/*"],
+ "@altertex/util/ser/*": ["Utilidades/Servicios/*"],
+ "@altertex/rol/*": ["Roles/*"],
+ "@altertex/rol/ctrl/*": ["Roles/Controladores/*"],
+ "@altertex/rol/datos/*": ["Roles/Datos/*"],
+ "@altertex/rol/repos/*": ["Roles/Datos/Repositorios/*"],
+ "@altertex/rol/rutas/*": ["Roles/Rutas/*"],
+ "@altertex/rol/rutasInd/*": ["Roles/Rutas/RutasIndividuales/*"],
+ "@altertex/pro/*": ["Productos/*"],
+ "@altertex/pro/ctrl/*": ["Productos/Controladores/*"],
+ "@altertex/pro/datos/*": ["Productos/Datos/*"],
+ "@altertex/pro/repos/*": ["Productos/Datos/Repositorios/*"],
+ "@altertex/pro/rutas/*": ["Productos/Rutas/*"],
+ "@altertex/pro/rutasInd/*": ["Productos/Rutas/RutasIndividuales/*"],
+ "@altertex/prove/*": ["Proveedores/*"],
+ "@altertex/prove/ctrl/*": ["Proveedores/Controladores/*"],
+ "@altertex/prove/datos/*": ["Proveedores/Datos/*"],
+ "@altertex/prove/repos/*": ["Proveedores/Datos/Repositorios/*"],
+ "@altertex/prove/rutas/*": ["Proveedores/Rutas/*"],
+ "@altertex/prove/rutasInd/*": ["Proveedores/Rutas/RutasIndividuales/*"],
+ "@altertex/cuota/*": ["Cuotas/*"],
+ "@altertex/cuota/ctrl/*": ["Cuotas/Controladores/*"],
+ "@altertex/cuota/datos/*": ["Cuotas/Datos/*"],
+ "@altertex/cuota/repos/*": ["Cuotas/Datos/Repositorios/*"],
+ "@altertex/cuota/rutas/*": ["Cuotas/Rutas/*"],
+ "@altertex/cuota/rutasInd/*": ["Cuotas/Rutas/RutasIndividuales/*"],
+ "@altertex/cat/*": ["Categorias/*"],
+ "@altertex/cat/ctrl/*": ["Categorias/Controladores/*"],
+ "@altertex/cat/datos/*": ["Categorias/Datos/*"],
+ "@altertex/cat/repos/*": ["Categorias/Datos/Repositorios/*"],
+ "@altertex/cat/rutas/*": ["Categorias/Rutas/*"],
+ "@altertex/cat/rutasInd/*": ["Categorias/Rutas/RutasIndividuales/*"],
+ "@altertex/setspro/*": ["SetsProductos/*"],
+ "@altertex/setspro/ctrl/*": ["SetsProductos/Controladores/*"],
+ "@altertex/setspro/datos/*": ["SetsProductos/Datos/*"],
+ "@altertex/setspro/repos/*": ["SetsProductos/Datos/Repositorios/*"],
+ "@altertex/setspro/rutas/*": ["SetsProductos/Rutas/*"],
+ "@altertex/setspro/rutasInd/*": ["SetsProductos/Rutas/RutasIndividuales/*"],
+ "@altertex/CRON/*": ["CRON_JOBS/*"],
+ "@altertex/CRON/ctrl/*": ["CRON_JOBS/Controladores/*"],
+ "@altertex/CRON/datos/*": ["CRON_JOBS/Datos/*"],
+ "@altertex/CRON/repos/*": ["CRON_JOBS/Datos/Repositorios/*"],
+ "@altertex/eve/*": ["Eventos/*"],
+ "@altertex/eve/ctrl/*": ["Eventos/Controladores/*"],
+ "@altertex/eve/datos/*": ["Eventos/Datos/*"],
+ "@altertex/eve/repos/*": ["Eventos/Datos/Repositorios/*"],
+ "@altertex/eve/rutas/*": ["Eventos/Rutas/*"],
+ "@altertex/eve/rutasInd/*": ["Eventos/Rutas/RutasIndividuales/*"],
+ "@altertex/pedidos/*": ["Pedidos/*"],
+ "@altertex/pedidos/ctrl/*": ["Pedidos/Controladores/*"],
+ "@altertex/pedidos/datos/*": ["Pedidos/Datos/*"],
+ "@altertex/pedidos/repos/*": ["Pedidos/Datos/Repositorios/*"],
+ "@altertex/pedidos/rutas/*": ["Pedidos/Rutas/*"],
+ "@altertex/pedidos/rutasInd/*": ["Pedidos/Rutas/RutasIndividuales/*"],
+ "@altertex/pago/ctrl/*": ["Pagos/Controladores/*"],
+ "@altertex/pago/datos/*": ["Pagos/Datos/*"],
+ "@altertex/pago/repos/*": ["Pagos/Datos/Repositorios/*"],
+ "@altertex/pago/rutas/*": ["Pagos/Rutas/*"],
+ "@altertex/pago/rutas/rutasInd/*": ["Pagos/Rutas/RutasIndividuales/*"]
+ }
+ },
+ "include": ["**/*.js"]
+}
diff --git a/package-lock.json b/package-lock.json
index e5e6c8ff..8474434f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,41 +1,74 @@
{
- "name": "prueba-arquitectura-backend-textiles",
+ "name": "backend-textiles",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "prueba-arquitectura-backend-textiles",
+ "name": "backend-textiles",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@aws-sdk/client-dynamodb": "^3.751.0",
- "@aws-sdk/client-s3": "^3.750.0",
+ "@aws-sdk/client-s3": "^3.808.0",
"@aws-sdk/lib-dynamodb": "^3.751.0",
+ "@aws-sdk/s3-request-presigner": "^3.787.0",
+ "@aws-sdk/types": "^3.775.0",
"aws-sdk": "^2.1692.0",
"bcryptjs": "^3.0.0",
"body-parser": "^1.20.3",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
+ "csurf": "^1.11.0",
+ "date-fns": "^4.1.0",
"dotenv": "^16.4.7",
+ "exceljs": "^4.4.0",
"express": "^4.21.2",
+ "helmet": "^8.1.0",
+ "i": "^0.3.7",
+ "json2csv": "^6.0.0-alpha.2",
"jsonwebtoken": "^9.0.2",
+ "module-alias": "^2.2.3",
"multer": "^1.4.5-lts.1",
"multer-s3": "^3.0.1",
+ "mysql2": "^3.14.0",
+ "node-cron": "^3.0.3",
+ "nodemon": "^3.1.9",
"pm2": "^5.4.3",
+ "qrcode": "^1.5.4",
+ "redis": "^5.1.0",
+ "speakeasy": "^2.0.0",
+ "supertest": "^7.1.0",
"swagger-jsdoc": "^6.2.8",
- "swagger-ui": "^5.20.0",
+ "swagger-ui": "^5.21.0",
"swagger-ui-express": "^5.0.1"
},
"devDependencies": {
"@eslint/js": "^9.23.0",
- "eslint": "^9.22.0"
+ "eslint": "^9.22.0",
+ "eslint-plugin-jsdoc": "^50.6.11",
+ "jest": "^29.7.0"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
}
},
"node_modules/@apidevtools/json-schema-ref-parser": {
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz",
"integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==",
+ "license": "MIT",
"dependencies": {
"@jsdevtools/ono": "^7.1.3",
"@types/json-schema": "^7.0.6",
@@ -47,6 +80,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz",
"integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==",
+ "license": "MIT",
"engines": {
"node": ">=10"
}
@@ -54,12 +88,14 @@
"node_modules/@apidevtools/swagger-methods": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz",
- "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg=="
+ "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==",
+ "license": "MIT"
},
"node_modules/@apidevtools/swagger-parser": {
"version": "10.0.3",
"resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz",
"integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==",
+ "license": "MIT",
"dependencies": {
"@apidevtools/json-schema-ref-parser": "^9.0.6",
"@apidevtools/openapi-schemas": "^2.0.4",
@@ -76,6 +112,7 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz",
"integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==",
+ "license": "Apache-2.0",
"dependencies": {
"@aws-crypto/util": "^5.2.0",
"@aws-sdk/types": "^3.222.0",
@@ -89,6 +126,7 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz",
"integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==",
+ "license": "Apache-2.0",
"dependencies": {
"@aws-crypto/util": "^5.2.0",
"@aws-sdk/types": "^3.222.0",
@@ -99,6 +137,7 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz",
"integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==",
+ "license": "Apache-2.0",
"dependencies": {
"@aws-crypto/supports-web-crypto": "^5.2.0",
"@aws-crypto/util": "^5.2.0",
@@ -112,6 +151,7 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
"integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
+ "license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
},
@@ -123,6 +163,7 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
"integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
+ "license": "Apache-2.0",
"dependencies": {
"@smithy/is-array-buffer": "^2.2.0",
"tslib": "^2.6.2"
@@ -135,6 +176,7 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
"integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
+ "license": "Apache-2.0",
"dependencies": {
"@smithy/util-buffer-from": "^2.2.0",
"tslib": "^2.6.2"
@@ -147,6 +189,7 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz",
"integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==",
+ "license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-js": "^5.2.0",
"@aws-crypto/supports-web-crypto": "^5.2.0",
@@ -161,6 +204,7 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
"integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
+ "license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
},
@@ -172,6 +216,7 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
"integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
+ "license": "Apache-2.0",
"dependencies": {
"@smithy/is-array-buffer": "^2.2.0",
"tslib": "^2.6.2"
@@ -184,6 +229,7 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
"integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
+ "license": "Apache-2.0",
"dependencies": {
"@smithy/util-buffer-from": "^2.2.0",
"tslib": "^2.6.2"
@@ -196,6 +242,7 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz",
"integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==",
+ "license": "Apache-2.0",
"dependencies": {
"@aws-crypto/util": "^5.2.0",
"@aws-sdk/types": "^3.222.0",
@@ -209,6 +256,7 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz",
"integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==",
+ "license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
}
@@ -217,6 +265,7 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz",
"integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==",
+ "license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "^3.222.0",
"@smithy/util-utf8": "^2.0.0",
@@ -227,6 +276,7 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
"integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
+ "license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
},
@@ -238,6 +288,7 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
"integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
+ "license": "Apache-2.0",
"dependencies": {
"@smithy/is-array-buffer": "^2.2.0",
"tslib": "^2.6.2"
@@ -250,6 +301,7 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
"integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
+ "license": "Apache-2.0",
"dependencies": {
"@smithy/util-buffer-from": "^2.2.0",
"tslib": "^2.6.2"
@@ -259,50 +311,51 @@
}
},
"node_modules/@aws-sdk/client-dynamodb": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.758.0.tgz",
- "integrity": "sha512-ZdVVCvmQ4wlV22HgYZKndIYNKkFfTLi8PIOF5rOkqthgYRTfVzKajrVbYebCs5jMDTk73LPLl2Ze/EYBEHKlBA==",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.808.0.tgz",
+ "integrity": "sha512-n1y4b+X/GQSGbVfegeoeii8rujBb1bjwdHmyKG5P2HILoVTpyLrO/sqQBDPCokjakZAPmJ2oe8ptqmOSw0Tv9Q==",
+ "license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/credential-provider-node": "3.758.0",
- "@aws-sdk/middleware-endpoint-discovery": "3.734.0",
- "@aws-sdk/middleware-host-header": "3.734.0",
- "@aws-sdk/middleware-logger": "3.734.0",
- "@aws-sdk/middleware-recursion-detection": "3.734.0",
- "@aws-sdk/middleware-user-agent": "3.758.0",
- "@aws-sdk/region-config-resolver": "3.734.0",
- "@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-endpoints": "3.743.0",
- "@aws-sdk/util-user-agent-browser": "3.734.0",
- "@aws-sdk/util-user-agent-node": "3.758.0",
- "@smithy/config-resolver": "^4.0.1",
- "@smithy/core": "^3.1.5",
- "@smithy/fetch-http-handler": "^5.0.1",
- "@smithy/hash-node": "^4.0.1",
- "@smithy/invalid-dependency": "^4.0.1",
- "@smithy/middleware-content-length": "^4.0.1",
- "@smithy/middleware-endpoint": "^4.0.6",
- "@smithy/middleware-retry": "^4.0.7",
- "@smithy/middleware-serde": "^4.0.2",
- "@smithy/middleware-stack": "^4.0.1",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/node-http-handler": "^4.0.3",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
- "@smithy/url-parser": "^4.0.1",
+ "@aws-sdk/core": "3.808.0",
+ "@aws-sdk/credential-provider-node": "3.808.0",
+ "@aws-sdk/middleware-endpoint-discovery": "3.808.0",
+ "@aws-sdk/middleware-host-header": "3.804.0",
+ "@aws-sdk/middleware-logger": "3.804.0",
+ "@aws-sdk/middleware-recursion-detection": "3.804.0",
+ "@aws-sdk/middleware-user-agent": "3.808.0",
+ "@aws-sdk/region-config-resolver": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@aws-sdk/util-endpoints": "3.808.0",
+ "@aws-sdk/util-user-agent-browser": "3.804.0",
+ "@aws-sdk/util-user-agent-node": "3.808.0",
+ "@smithy/config-resolver": "^4.1.2",
+ "@smithy/core": "^3.3.1",
+ "@smithy/fetch-http-handler": "^5.0.2",
+ "@smithy/hash-node": "^4.0.2",
+ "@smithy/invalid-dependency": "^4.0.2",
+ "@smithy/middleware-content-length": "^4.0.2",
+ "@smithy/middleware-endpoint": "^4.1.4",
+ "@smithy/middleware-retry": "^4.1.5",
+ "@smithy/middleware-serde": "^4.0.3",
+ "@smithy/middleware-stack": "^4.0.2",
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/node-http-handler": "^4.0.4",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/smithy-client": "^4.2.4",
+ "@smithy/types": "^4.2.0",
+ "@smithy/url-parser": "^4.0.2",
"@smithy/util-base64": "^4.0.0",
"@smithy/util-body-length-browser": "^4.0.0",
"@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.7",
- "@smithy/util-defaults-mode-node": "^4.0.7",
- "@smithy/util-endpoints": "^3.0.1",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-retry": "^4.0.1",
+ "@smithy/util-defaults-mode-browser": "^4.0.12",
+ "@smithy/util-defaults-mode-node": "^4.0.12",
+ "@smithy/util-endpoints": "^3.0.4",
+ "@smithy/util-middleware": "^4.0.2",
+ "@smithy/util-retry": "^4.0.3",
"@smithy/util-utf8": "^4.0.0",
- "@smithy/util-waiter": "^4.0.2",
+ "@smithy/util-waiter": "^4.0.3",
"@types/uuid": "^9.0.1",
"tslib": "^2.6.2",
"uuid": "^9.0.1"
@@ -312,65 +365,66 @@
}
},
"node_modules/@aws-sdk/client-s3": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.758.0.tgz",
- "integrity": "sha512-f8SlhU9/93OC/WEI6xVJf/x/GoQFj9a/xXK6QCtr5fvCjfSLgMVFmKTiIl/tgtDRzxUDc8YS6EGtbHjJ3Y/atg==",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.808.0.tgz",
+ "integrity": "sha512-8RY3Jsm84twmYfiqnMkxznuY6pBX7y2GiuEJVdW1ZJLXRDOiCPkTBHsO6jUwppfMua7HRhO2OTAdWr7aSBAdPw==",
+ "license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha1-browser": "5.2.0",
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/credential-provider-node": "3.758.0",
- "@aws-sdk/middleware-bucket-endpoint": "3.734.0",
- "@aws-sdk/middleware-expect-continue": "3.734.0",
- "@aws-sdk/middleware-flexible-checksums": "3.758.0",
- "@aws-sdk/middleware-host-header": "3.734.0",
- "@aws-sdk/middleware-location-constraint": "3.734.0",
- "@aws-sdk/middleware-logger": "3.734.0",
- "@aws-sdk/middleware-recursion-detection": "3.734.0",
- "@aws-sdk/middleware-sdk-s3": "3.758.0",
- "@aws-sdk/middleware-ssec": "3.734.0",
- "@aws-sdk/middleware-user-agent": "3.758.0",
- "@aws-sdk/region-config-resolver": "3.734.0",
- "@aws-sdk/signature-v4-multi-region": "3.758.0",
- "@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-endpoints": "3.743.0",
- "@aws-sdk/util-user-agent-browser": "3.734.0",
- "@aws-sdk/util-user-agent-node": "3.758.0",
- "@aws-sdk/xml-builder": "3.734.0",
- "@smithy/config-resolver": "^4.0.1",
- "@smithy/core": "^3.1.5",
- "@smithy/eventstream-serde-browser": "^4.0.1",
- "@smithy/eventstream-serde-config-resolver": "^4.0.1",
- "@smithy/eventstream-serde-node": "^4.0.1",
- "@smithy/fetch-http-handler": "^5.0.1",
- "@smithy/hash-blob-browser": "^4.0.1",
- "@smithy/hash-node": "^4.0.1",
- "@smithy/hash-stream-node": "^4.0.1",
- "@smithy/invalid-dependency": "^4.0.1",
- "@smithy/md5-js": "^4.0.1",
- "@smithy/middleware-content-length": "^4.0.1",
- "@smithy/middleware-endpoint": "^4.0.6",
- "@smithy/middleware-retry": "^4.0.7",
- "@smithy/middleware-serde": "^4.0.2",
- "@smithy/middleware-stack": "^4.0.1",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/node-http-handler": "^4.0.3",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
- "@smithy/url-parser": "^4.0.1",
+ "@aws-sdk/core": "3.808.0",
+ "@aws-sdk/credential-provider-node": "3.808.0",
+ "@aws-sdk/middleware-bucket-endpoint": "3.808.0",
+ "@aws-sdk/middleware-expect-continue": "3.804.0",
+ "@aws-sdk/middleware-flexible-checksums": "3.808.0",
+ "@aws-sdk/middleware-host-header": "3.804.0",
+ "@aws-sdk/middleware-location-constraint": "3.804.0",
+ "@aws-sdk/middleware-logger": "3.804.0",
+ "@aws-sdk/middleware-recursion-detection": "3.804.0",
+ "@aws-sdk/middleware-sdk-s3": "3.808.0",
+ "@aws-sdk/middleware-ssec": "3.804.0",
+ "@aws-sdk/middleware-user-agent": "3.808.0",
+ "@aws-sdk/region-config-resolver": "3.808.0",
+ "@aws-sdk/signature-v4-multi-region": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@aws-sdk/util-endpoints": "3.808.0",
+ "@aws-sdk/util-user-agent-browser": "3.804.0",
+ "@aws-sdk/util-user-agent-node": "3.808.0",
+ "@aws-sdk/xml-builder": "3.804.0",
+ "@smithy/config-resolver": "^4.1.2",
+ "@smithy/core": "^3.3.1",
+ "@smithy/eventstream-serde-browser": "^4.0.2",
+ "@smithy/eventstream-serde-config-resolver": "^4.1.0",
+ "@smithy/eventstream-serde-node": "^4.0.2",
+ "@smithy/fetch-http-handler": "^5.0.2",
+ "@smithy/hash-blob-browser": "^4.0.2",
+ "@smithy/hash-node": "^4.0.2",
+ "@smithy/hash-stream-node": "^4.0.2",
+ "@smithy/invalid-dependency": "^4.0.2",
+ "@smithy/md5-js": "^4.0.2",
+ "@smithy/middleware-content-length": "^4.0.2",
+ "@smithy/middleware-endpoint": "^4.1.4",
+ "@smithy/middleware-retry": "^4.1.5",
+ "@smithy/middleware-serde": "^4.0.3",
+ "@smithy/middleware-stack": "^4.0.2",
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/node-http-handler": "^4.0.4",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/smithy-client": "^4.2.4",
+ "@smithy/types": "^4.2.0",
+ "@smithy/url-parser": "^4.0.2",
"@smithy/util-base64": "^4.0.0",
"@smithy/util-body-length-browser": "^4.0.0",
"@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.7",
- "@smithy/util-defaults-mode-node": "^4.0.7",
- "@smithy/util-endpoints": "^3.0.1",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-retry": "^4.0.1",
- "@smithy/util-stream": "^4.1.2",
+ "@smithy/util-defaults-mode-browser": "^4.0.12",
+ "@smithy/util-defaults-mode-node": "^4.0.12",
+ "@smithy/util-endpoints": "^3.0.4",
+ "@smithy/util-middleware": "^4.0.2",
+ "@smithy/util-retry": "^4.0.3",
+ "@smithy/util-stream": "^4.2.0",
"@smithy/util-utf8": "^4.0.0",
- "@smithy/util-waiter": "^4.0.2",
+ "@smithy/util-waiter": "^4.0.3",
"tslib": "^2.6.2"
},
"engines": {
@@ -378,46 +432,47 @@
}
},
"node_modules/@aws-sdk/client-sso": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.758.0.tgz",
- "integrity": "sha512-BoGO6IIWrLyLxQG6txJw6RT2urmbtlwfggapNCrNPyYjlXpzTSJhBYjndg7TpDATFd0SXL0zm8y/tXsUXNkdYQ==",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.808.0.tgz",
+ "integrity": "sha512-NxGomD0x9q30LPOXf4x7haOm6l2BJdLEzpiC/bPEXUkf2+4XudMQumMA/hDfErY5hCE19mFAouoO465m3Gl3JQ==",
+ "license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/middleware-host-header": "3.734.0",
- "@aws-sdk/middleware-logger": "3.734.0",
- "@aws-sdk/middleware-recursion-detection": "3.734.0",
- "@aws-sdk/middleware-user-agent": "3.758.0",
- "@aws-sdk/region-config-resolver": "3.734.0",
- "@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-endpoints": "3.743.0",
- "@aws-sdk/util-user-agent-browser": "3.734.0",
- "@aws-sdk/util-user-agent-node": "3.758.0",
- "@smithy/config-resolver": "^4.0.1",
- "@smithy/core": "^3.1.5",
- "@smithy/fetch-http-handler": "^5.0.1",
- "@smithy/hash-node": "^4.0.1",
- "@smithy/invalid-dependency": "^4.0.1",
- "@smithy/middleware-content-length": "^4.0.1",
- "@smithy/middleware-endpoint": "^4.0.6",
- "@smithy/middleware-retry": "^4.0.7",
- "@smithy/middleware-serde": "^4.0.2",
- "@smithy/middleware-stack": "^4.0.1",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/node-http-handler": "^4.0.3",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
- "@smithy/url-parser": "^4.0.1",
+ "@aws-sdk/core": "3.808.0",
+ "@aws-sdk/middleware-host-header": "3.804.0",
+ "@aws-sdk/middleware-logger": "3.804.0",
+ "@aws-sdk/middleware-recursion-detection": "3.804.0",
+ "@aws-sdk/middleware-user-agent": "3.808.0",
+ "@aws-sdk/region-config-resolver": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@aws-sdk/util-endpoints": "3.808.0",
+ "@aws-sdk/util-user-agent-browser": "3.804.0",
+ "@aws-sdk/util-user-agent-node": "3.808.0",
+ "@smithy/config-resolver": "^4.1.2",
+ "@smithy/core": "^3.3.1",
+ "@smithy/fetch-http-handler": "^5.0.2",
+ "@smithy/hash-node": "^4.0.2",
+ "@smithy/invalid-dependency": "^4.0.2",
+ "@smithy/middleware-content-length": "^4.0.2",
+ "@smithy/middleware-endpoint": "^4.1.4",
+ "@smithy/middleware-retry": "^4.1.5",
+ "@smithy/middleware-serde": "^4.0.3",
+ "@smithy/middleware-stack": "^4.0.2",
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/node-http-handler": "^4.0.4",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/smithy-client": "^4.2.4",
+ "@smithy/types": "^4.2.0",
+ "@smithy/url-parser": "^4.0.2",
"@smithy/util-base64": "^4.0.0",
"@smithy/util-body-length-browser": "^4.0.0",
"@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.7",
- "@smithy/util-defaults-mode-node": "^4.0.7",
- "@smithy/util-endpoints": "^3.0.1",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-retry": "^4.0.1",
+ "@smithy/util-defaults-mode-browser": "^4.0.12",
+ "@smithy/util-defaults-mode-node": "^4.0.12",
+ "@smithy/util-endpoints": "^3.0.4",
+ "@smithy/util-middleware": "^4.0.2",
+ "@smithy/util-retry": "^4.0.3",
"@smithy/util-utf8": "^4.0.0",
"tslib": "^2.6.2"
},
@@ -426,19 +481,20 @@
}
},
"node_modules/@aws-sdk/core": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.758.0.tgz",
- "integrity": "sha512-0RswbdR9jt/XKemaLNuxi2gGr4xGlHyGxkTdhSQzCyUe9A9OPCoLl3rIESRguQEech+oJnbHk/wuiwHqTuP9sg==",
- "dependencies": {
- "@aws-sdk/types": "3.734.0",
- "@smithy/core": "^3.1.5",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/signature-v4": "^5.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
- "@smithy/util-middleware": "^4.0.1",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.808.0.tgz",
+ "integrity": "sha512-+nTmxJVIPtAarGq9Fd/uU2qU/Ngfb9EntT0/kwXdKKMI0wU9fQNWi10xSTVeqOtzWERbQpOJgBAdta+v3W7cng==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/core": "^3.3.1",
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/signature-v4": "^5.1.0",
+ "@smithy/smithy-client": "^4.2.4",
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-middleware": "^4.0.2",
"fast-xml-parser": "4.4.1",
"tslib": "^2.6.2"
},
@@ -447,14 +503,15 @@
}
},
"node_modules/@aws-sdk/credential-provider-env": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.758.0.tgz",
- "integrity": "sha512-N27eFoRrO6MeUNumtNHDW9WOiwfd59LPXPqDrIa3kWL/s+fOKFHb9xIcF++bAwtcZnAxKkgpDCUP+INNZskE+w==",
- "dependencies": {
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/types": "3.734.0",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.808.0.tgz",
+ "integrity": "sha512-snPRQnwG9PV4kYHQimo1tenf7P974RcdxkHUThzWSxPEV7HpjxTFYNWGlKbOKBhL4AcgeCVeiZ/j+zveF2lEPA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -462,19 +519,20 @@
}
},
"node_modules/@aws-sdk/credential-provider-http": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.758.0.tgz",
- "integrity": "sha512-Xt9/U8qUCiw1hihztWkNeIR+arg6P+yda10OuCHX6kFVx3auTlU7+hCqs3UxqniGU4dguHuftf3mRpi5/GJ33Q==",
- "dependencies": {
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/types": "3.734.0",
- "@smithy/fetch-http-handler": "^5.0.1",
- "@smithy/node-http-handler": "^4.0.3",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
- "@smithy/util-stream": "^4.1.2",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.808.0.tgz",
+ "integrity": "sha512-gNXjlx3BIUeX7QpVqxbjBxG6zm45lC39QvUIo92WzEJd2OTPcR8TU0OTTsgq/lpn2FrKcISj5qXvhWykd41+CA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/fetch-http-handler": "^5.0.2",
+ "@smithy/node-http-handler": "^4.0.4",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/smithy-client": "^4.2.4",
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-stream": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -482,22 +540,23 @@
}
},
"node_modules/@aws-sdk/credential-provider-ini": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.758.0.tgz",
- "integrity": "sha512-cymSKMcP5d+OsgetoIZ5QCe1wnp2Q/tq+uIxVdh9MbfdBBEnl9Ecq6dH6VlYS89sp4QKuxHxkWXVnbXU3Q19Aw==",
- "dependencies": {
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/credential-provider-env": "3.758.0",
- "@aws-sdk/credential-provider-http": "3.758.0",
- "@aws-sdk/credential-provider-process": "3.758.0",
- "@aws-sdk/credential-provider-sso": "3.758.0",
- "@aws-sdk/credential-provider-web-identity": "3.758.0",
- "@aws-sdk/nested-clients": "3.758.0",
- "@aws-sdk/types": "3.734.0",
- "@smithy/credential-provider-imds": "^4.0.1",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/shared-ini-file-loader": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.808.0.tgz",
+ "integrity": "sha512-Y53CW0pCvFQQEvtVFwExCCMbTg+6NOl8b3YOuZVzPmVmDoW7M1JIn9IScesqoGERXL3VoXny6nYTsZj+vfpp7Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.808.0",
+ "@aws-sdk/credential-provider-env": "3.808.0",
+ "@aws-sdk/credential-provider-http": "3.808.0",
+ "@aws-sdk/credential-provider-process": "3.808.0",
+ "@aws-sdk/credential-provider-sso": "3.808.0",
+ "@aws-sdk/credential-provider-web-identity": "3.808.0",
+ "@aws-sdk/nested-clients": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/credential-provider-imds": "^4.0.2",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/shared-ini-file-loader": "^4.0.2",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -505,21 +564,22 @@
}
},
"node_modules/@aws-sdk/credential-provider-node": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.758.0.tgz",
- "integrity": "sha512-+DaMv63wiq7pJrhIQzZYMn4hSarKiizDoJRvyR7WGhnn0oQ/getX9Z0VNCV3i7lIFoLNTb7WMmQ9k7+z/uD5EQ==",
- "dependencies": {
- "@aws-sdk/credential-provider-env": "3.758.0",
- "@aws-sdk/credential-provider-http": "3.758.0",
- "@aws-sdk/credential-provider-ini": "3.758.0",
- "@aws-sdk/credential-provider-process": "3.758.0",
- "@aws-sdk/credential-provider-sso": "3.758.0",
- "@aws-sdk/credential-provider-web-identity": "3.758.0",
- "@aws-sdk/types": "3.734.0",
- "@smithy/credential-provider-imds": "^4.0.1",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/shared-ini-file-loader": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.808.0.tgz",
+ "integrity": "sha512-lASHlXJ6U5Cpnt9Gs+mWaaSmWcEibr1AFGhp+5UNvfyd+UU2Oiwgbo7rYXygmaVDGkbfXEiTkgYtoNOBSddnWQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/credential-provider-env": "3.808.0",
+ "@aws-sdk/credential-provider-http": "3.808.0",
+ "@aws-sdk/credential-provider-ini": "3.808.0",
+ "@aws-sdk/credential-provider-process": "3.808.0",
+ "@aws-sdk/credential-provider-sso": "3.808.0",
+ "@aws-sdk/credential-provider-web-identity": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/credential-provider-imds": "^4.0.2",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/shared-ini-file-loader": "^4.0.2",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -527,15 +587,16 @@
}
},
"node_modules/@aws-sdk/credential-provider-process": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.758.0.tgz",
- "integrity": "sha512-AzcY74QTPqcbXWVgjpPZ3HOmxQZYPROIBz2YINF0OQk0MhezDWV/O7Xec+K1+MPGQO3qS6EDrUUlnPLjsqieHA==",
- "dependencies": {
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/types": "3.734.0",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/shared-ini-file-loader": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.808.0.tgz",
+ "integrity": "sha512-ZLqp+xsQUatoo8pMozcfLwf/pwfXeIk0w3n0Lo/rWBgT3RcdECmmPCRcnkYBqxHQyE66aS9HiJezZUwMYPqh6w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/shared-ini-file-loader": "^4.0.2",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -543,17 +604,18 @@
}
},
"node_modules/@aws-sdk/credential-provider-sso": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.758.0.tgz",
- "integrity": "sha512-x0FYJqcOLUCv8GLLFDYMXRAQKGjoM+L0BG4BiHYZRDf24yQWFCAZsCQAYKo6XZYh2qznbsW6f//qpyJ5b0QVKQ==",
- "dependencies": {
- "@aws-sdk/client-sso": "3.758.0",
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/token-providers": "3.758.0",
- "@aws-sdk/types": "3.734.0",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/shared-ini-file-loader": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.808.0.tgz",
+ "integrity": "sha512-gWZByAokHX+aps1+syIW/hbKUBrjE2RpPRd/RGQvrBbVVgwsJzsHKsW0zy1B6mgARPG6IahmSUMjNkBCVsiAgw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/client-sso": "3.808.0",
+ "@aws-sdk/core": "3.808.0",
+ "@aws-sdk/token-providers": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/shared-ini-file-loader": "^4.0.2",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -561,15 +623,16 @@
}
},
"node_modules/@aws-sdk/credential-provider-web-identity": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.758.0.tgz",
- "integrity": "sha512-XGguXhBqiCXMXRxcfCAVPlMbm3VyJTou79r/3mxWddHWF0XbhaQiBIbUz6vobVTD25YQRbWSmSch7VA8kI5Lrw==",
- "dependencies": {
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/nested-clients": "3.758.0",
- "@aws-sdk/types": "3.734.0",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.808.0.tgz",
+ "integrity": "sha512-SsGa1Gfa05aJM/qYOtHmfg0OKKW6Fl6kyMCcai63jWDVDYy0QSHcesnqRayJolISkdsVK6bqoWoFcPxiopcFcg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.808.0",
+ "@aws-sdk/nested-clients": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -577,9 +640,10 @@
}
},
"node_modules/@aws-sdk/endpoint-cache": {
- "version": "3.723.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.723.0.tgz",
- "integrity": "sha512-2+a4WXRc+07uiPR+zJiPGKSOWaNJQNqitkks+6Hhm/haTLJqNVTgY2OWDh2PXvwMNpKB+AlGdhE65Oy6NzUgXg==",
+ "version": "3.804.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.804.0.tgz",
+ "integrity": "sha512-TQVDkA/lV6ua75ELZaichMzlp6x7tDa1bqdy/+0ZftmODPtKXuOOEcJxmdN7Ui/YRo1gkRz2D9txYy7IlNg1Og==",
+ "license": "Apache-2.0",
"dependencies": {
"mnemonist": "0.38.3",
"tslib": "^2.6.2"
@@ -589,32 +653,34 @@
}
},
"node_modules/@aws-sdk/lib-dynamodb": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.758.0.tgz",
- "integrity": "sha512-lkxh7nkFMHY2zbPxhGQz7hVA43yRPu+ERrSiRu7I11arAOz/MJlt7MjHmt0B8x7x6isF1utNixkU28HKh9hgWQ==",
- "dependencies": {
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/util-dynamodb": "3.758.0",
- "@smithy/core": "^3.1.5",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.808.0.tgz",
+ "integrity": "sha512-okdntX2StMqWHvUqEN/X8HA4B51T19iUWzZ0HTpbUCi4Zo6PEZvmNBSgCFzoGQO3BeYDD0E1OVCGkdTm/PM6Sg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.808.0",
+ "@aws-sdk/util-dynamodb": "3.808.0",
+ "@smithy/core": "^3.3.1",
+ "@smithy/smithy-client": "^4.2.4",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
},
"peerDependencies": {
- "@aws-sdk/client-dynamodb": "^3.758.0"
+ "@aws-sdk/client-dynamodb": "^3.808.0"
}
},
"node_modules/@aws-sdk/lib-storage": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.758.0.tgz",
- "integrity": "sha512-g07y7rA505zaTJNPTmvW4zYJA3gThFDE1be7kBUKhTKAdwv8jVSbOiAy2AhClXs2evSUoQiFFtD1xWxLRXPPRQ==",
- "dependencies": {
- "@smithy/abort-controller": "^4.0.1",
- "@smithy/middleware-endpoint": "^4.0.6",
- "@smithy/smithy-client": "^4.1.6",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.808.0.tgz",
+ "integrity": "sha512-gEdiBuqPjmMA0Z2RtppIdcMQH1KDeRM//+DWcVC9gU9pMJ5S/LEwCmWEVh3/C2n/Sehv71b7x0GKGxHO/yBrwA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/abort-controller": "^4.0.2",
+ "@smithy/middleware-endpoint": "^4.1.4",
+ "@smithy/smithy-client": "^4.2.4",
"buffer": "5.6.0",
"events": "3.3.0",
"stream-browserify": "3.0.0",
@@ -624,13 +690,14 @@
"node": ">=18.0.0"
},
"peerDependencies": {
- "@aws-sdk/client-s3": "^3.758.0"
+ "@aws-sdk/client-s3": "^3.808.0"
}
},
"node_modules/@aws-sdk/lib-storage/node_modules/buffer": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz",
"integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==",
+ "license": "MIT",
"dependencies": {
"base64-js": "^1.0.2",
"ieee754": "^1.1.4"
@@ -640,20 +707,22 @@
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "license": "MIT",
"engines": {
"node": ">=0.8.x"
}
},
"node_modules/@aws-sdk/middleware-bucket-endpoint": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.734.0.tgz",
- "integrity": "sha512-etC7G18aF7KdZguW27GE/wpbrNmYLVT755EsFc8kXpZj8D6AFKxc7OuveinJmiy0bYXAMspJUWsF6CrGpOw6CQ==",
- "dependencies": {
- "@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-arn-parser": "3.723.0",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.808.0.tgz",
+ "integrity": "sha512-wEPlNcs8dir9lXbuviEGtSzYSxG/NRKQrJk5ybOc7OpPGHovsN+QhDOdY3lcjOFdwMTiMIG9foUkPz3zBpLB1A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.804.0",
+ "@aws-sdk/util-arn-parser": "3.804.0",
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/types": "^4.2.0",
"@smithy/util-config-provider": "^4.0.0",
"tslib": "^2.6.2"
},
@@ -662,15 +731,16 @@
}
},
"node_modules/@aws-sdk/middleware-endpoint-discovery": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.734.0.tgz",
- "integrity": "sha512-hE3x9Sbqy64g/lcFIq7BF9IS1tSOyfBCyHf1xBgevWeFIDTWh647URuCNWoEwtw4HMEhO2MDUQcKf1PFh1dNDA==",
- "dependencies": {
- "@aws-sdk/endpoint-cache": "3.723.0",
- "@aws-sdk/types": "3.734.0",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.808.0.tgz",
+ "integrity": "sha512-h8LAIO6tuA0JAahrg+oSIVZpb6rhJOFVDDqYNQVp6ZdawlIzpZcc1sa+XVZvarBnThNKqvLTSGK7boSRmaLAwg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/endpoint-cache": "3.804.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -678,13 +748,14 @@
}
},
"node_modules/@aws-sdk/middleware-expect-continue": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.734.0.tgz",
- "integrity": "sha512-P38/v1l6HjuB2aFUewt7ueAW5IvKkFcv5dalPtbMGRhLeyivBOHwbCyuRKgVs7z7ClTpu9EaViEGki2jEQqEsQ==",
- "dependencies": {
- "@aws-sdk/types": "3.734.0",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.804.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.804.0.tgz",
+ "integrity": "sha512-YW1hySBolALMII6C8y7Z0CRG2UX1dGJjLEBNFeefhO/xP7ZuE1dvnmfJGaEuBMnvc3wkRS63VZ3aqX6sevM1CA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -692,21 +763,22 @@
}
},
"node_modules/@aws-sdk/middleware-flexible-checksums": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.758.0.tgz",
- "integrity": "sha512-o8Rk71S08YTKLoSobucjnbj97OCGaXgpEDNKXpXaavUM5xLNoHCLSUPRCiEN86Ivqxg1n17Y2nSRhfbsveOXXA==",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.808.0.tgz",
+ "integrity": "sha512-NW1yoTYDH2h8ycqMPNkvW3d1XT2vEeXfXclagL2tv82P7Qt7vPXYcObs/YtETvNZ7hdnmOftJ/IJv7YrFC8vtQ==",
+ "license": "Apache-2.0",
"dependencies": {
"@aws-crypto/crc32": "5.2.0",
"@aws-crypto/crc32c": "5.2.0",
"@aws-crypto/util": "5.2.0",
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/types": "3.734.0",
+ "@aws-sdk/core": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
"@smithy/is-array-buffer": "^4.0.0",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-stream": "^4.1.2",
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-middleware": "^4.0.2",
+ "@smithy/util-stream": "^4.2.0",
"@smithy/util-utf8": "^4.0.0",
"tslib": "^2.6.2"
},
@@ -715,13 +787,14 @@
}
},
"node_modules/@aws-sdk/middleware-host-header": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.734.0.tgz",
- "integrity": "sha512-LW7RRgSOHHBzWZnigNsDIzu3AiwtjeI2X66v+Wn1P1u+eXssy1+up4ZY/h+t2sU4LU36UvEf+jrZti9c6vRnFw==",
- "dependencies": {
- "@aws-sdk/types": "3.734.0",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.804.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.804.0.tgz",
+ "integrity": "sha512-bum1hLVBrn2lJCi423Z2fMUYtsbkGI2s4N+2RI2WSjvbaVyMSv/WcejIrjkqiiMR+2Y7m5exgoKeg4/TODLDPQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -729,12 +802,13 @@
}
},
"node_modules/@aws-sdk/middleware-location-constraint": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.734.0.tgz",
- "integrity": "sha512-EJEIXwCQhto/cBfHdm3ZOeLxd2NlJD+X2F+ZTOxzokuhBtY0IONfC/91hOo5tWQweerojwshSMHRCKzRv1tlwg==",
+ "version": "3.804.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.804.0.tgz",
+ "integrity": "sha512-AMtKnllIWKgoo7hiJfphLYotEwTERfjVMO2+cKAncz9w1g+bnYhHxiVhJJoR94y047c06X4PU5MsTxvdQ73Znw==",
+ "license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.734.0",
- "@smithy/types": "^4.1.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -742,12 +816,13 @@
}
},
"node_modules/@aws-sdk/middleware-logger": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.734.0.tgz",
- "integrity": "sha512-mUMFITpJUW3LcKvFok176eI5zXAUomVtahb9IQBwLzkqFYOrMJvWAvoV4yuxrJ8TlQBG8gyEnkb9SnhZvjg67w==",
+ "version": "3.804.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.804.0.tgz",
+ "integrity": "sha512-w/qLwL3iq0KOPQNat0Kb7sKndl9BtceigINwBU7SpkYWX9L/Lem6f8NPEKrC9Tl4wDBht3Yztub4oRTy/horJA==",
+ "license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.734.0",
- "@smithy/types": "^4.1.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -755,13 +830,14 @@
}
},
"node_modules/@aws-sdk/middleware-recursion-detection": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.734.0.tgz",
- "integrity": "sha512-CUat2d9ITsFc2XsmeiRQO96iWpxSKYFjxvj27Hc7vo87YUHRnfMfnc8jw1EpxEwMcvBD7LsRa6vDNky6AjcrFA==",
- "dependencies": {
- "@aws-sdk/types": "3.734.0",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.804.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.804.0.tgz",
+ "integrity": "sha512-zqHOrvLRdsUdN/ehYfZ9Tf8svhbiLLz5VaWUz22YndFv6m9qaAcijkpAOlKexsv3nLBMJdSdJ6GUTAeIy3BZzw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -769,22 +845,23 @@
}
},
"node_modules/@aws-sdk/middleware-sdk-s3": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.758.0.tgz",
- "integrity": "sha512-6mJ2zyyHPYSV6bAcaFpsdoXZJeQlR1QgBnZZ6juY/+dcYiuyWCdyLUbGzSZSE7GTfx6i+9+QWFeoIMlWKgU63A==",
- "dependencies": {
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-arn-parser": "3.723.0",
- "@smithy/core": "^3.1.5",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/signature-v4": "^5.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.808.0.tgz",
+ "integrity": "sha512-qvyJTDf0HIsPpZzBUqhNQm5g8stAn2EOwVsaAolsOHuBsdaBAE/s/NgPzazDlSXwdF0ITvsIouUVDCn4fJGJqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@aws-sdk/util-arn-parser": "3.804.0",
+ "@smithy/core": "^3.3.1",
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/signature-v4": "^5.1.0",
+ "@smithy/smithy-client": "^4.2.4",
+ "@smithy/types": "^4.2.0",
"@smithy/util-config-provider": "^4.0.0",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-stream": "^4.1.2",
+ "@smithy/util-middleware": "^4.0.2",
+ "@smithy/util-stream": "^4.2.0",
"@smithy/util-utf8": "^4.0.0",
"tslib": "^2.6.2"
},
@@ -793,12 +870,13 @@
}
},
"node_modules/@aws-sdk/middleware-ssec": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.734.0.tgz",
- "integrity": "sha512-d4yd1RrPW/sspEXizq2NSOUivnheac6LPeLSLnaeTbBG9g1KqIqvCzP1TfXEqv2CrWfHEsWtJpX7oyjySSPvDQ==",
+ "version": "3.804.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.804.0.tgz",
+ "integrity": "sha512-Tk8jK0gOIUBvEPTz/wwSlP1V70zVQ3QYqsLPAjQRMO6zfOK9ax31dln3MgKvFDJxBydS2tS3wsn53v+brxDxTA==",
+ "license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.734.0",
- "@smithy/types": "^4.1.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -806,16 +884,17 @@
}
},
"node_modules/@aws-sdk/middleware-user-agent": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.758.0.tgz",
- "integrity": "sha512-iNyehQXtQlj69JCgfaOssgZD4HeYGOwxcaKeG6F+40cwBjTAi0+Ph1yfDwqk2qiBPIRWJ/9l2LodZbxiBqgrwg==",
- "dependencies": {
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-endpoints": "3.743.0",
- "@smithy/core": "^3.1.5",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.808.0.tgz",
+ "integrity": "sha512-VckV6l5cf/rL3EtgzSHVTTD4mI0gd8UxDDWbKJsxbQ2bpNPDQG2L1wWGLaolTSzjEJ5f3ijDwQrNDbY9l85Mmg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@aws-sdk/util-endpoints": "3.808.0",
+ "@smithy/core": "^3.3.1",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -823,46 +902,47 @@
}
},
"node_modules/@aws-sdk/nested-clients": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.758.0.tgz",
- "integrity": "sha512-YZ5s7PSvyF3Mt2h1EQulCG93uybprNGbBkPmVuy/HMMfbFTt4iL3SbKjxqvOZelm86epFfj7pvK7FliI2WOEcg==",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.808.0.tgz",
+ "integrity": "sha512-NparPojwoBul7XPCasy4psFMJbw7Ys4bz8lVB93ljEUD4VV7mM7zwK27Uhz20B8mBFGmFEoAprPsVymJcK9Vcw==",
+ "license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/middleware-host-header": "3.734.0",
- "@aws-sdk/middleware-logger": "3.734.0",
- "@aws-sdk/middleware-recursion-detection": "3.734.0",
- "@aws-sdk/middleware-user-agent": "3.758.0",
- "@aws-sdk/region-config-resolver": "3.734.0",
- "@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-endpoints": "3.743.0",
- "@aws-sdk/util-user-agent-browser": "3.734.0",
- "@aws-sdk/util-user-agent-node": "3.758.0",
- "@smithy/config-resolver": "^4.0.1",
- "@smithy/core": "^3.1.5",
- "@smithy/fetch-http-handler": "^5.0.1",
- "@smithy/hash-node": "^4.0.1",
- "@smithy/invalid-dependency": "^4.0.1",
- "@smithy/middleware-content-length": "^4.0.1",
- "@smithy/middleware-endpoint": "^4.0.6",
- "@smithy/middleware-retry": "^4.0.7",
- "@smithy/middleware-serde": "^4.0.2",
- "@smithy/middleware-stack": "^4.0.1",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/node-http-handler": "^4.0.3",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
- "@smithy/url-parser": "^4.0.1",
+ "@aws-sdk/core": "3.808.0",
+ "@aws-sdk/middleware-host-header": "3.804.0",
+ "@aws-sdk/middleware-logger": "3.804.0",
+ "@aws-sdk/middleware-recursion-detection": "3.804.0",
+ "@aws-sdk/middleware-user-agent": "3.808.0",
+ "@aws-sdk/region-config-resolver": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@aws-sdk/util-endpoints": "3.808.0",
+ "@aws-sdk/util-user-agent-browser": "3.804.0",
+ "@aws-sdk/util-user-agent-node": "3.808.0",
+ "@smithy/config-resolver": "^4.1.2",
+ "@smithy/core": "^3.3.1",
+ "@smithy/fetch-http-handler": "^5.0.2",
+ "@smithy/hash-node": "^4.0.2",
+ "@smithy/invalid-dependency": "^4.0.2",
+ "@smithy/middleware-content-length": "^4.0.2",
+ "@smithy/middleware-endpoint": "^4.1.4",
+ "@smithy/middleware-retry": "^4.1.5",
+ "@smithy/middleware-serde": "^4.0.3",
+ "@smithy/middleware-stack": "^4.0.2",
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/node-http-handler": "^4.0.4",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/smithy-client": "^4.2.4",
+ "@smithy/types": "^4.2.0",
+ "@smithy/url-parser": "^4.0.2",
"@smithy/util-base64": "^4.0.0",
"@smithy/util-body-length-browser": "^4.0.0",
"@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.7",
- "@smithy/util-defaults-mode-node": "^4.0.7",
- "@smithy/util-endpoints": "^3.0.1",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-retry": "^4.0.1",
+ "@smithy/util-defaults-mode-browser": "^4.0.12",
+ "@smithy/util-defaults-mode-node": "^4.0.12",
+ "@smithy/util-endpoints": "^3.0.4",
+ "@smithy/util-middleware": "^4.0.2",
+ "@smithy/util-retry": "^4.0.3",
"@smithy/util-utf8": "^4.0.0",
"tslib": "^2.6.2"
},
@@ -871,15 +951,35 @@
}
},
"node_modules/@aws-sdk/region-config-resolver": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.734.0.tgz",
- "integrity": "sha512-Lvj1kPRC5IuJBr9DyJ9T9/plkh+EfKLy+12s/mykOy1JaKHDpvj+XGy2YO6YgYVOb8JFtaqloid+5COtje4JTQ==",
- "dependencies": {
- "@aws-sdk/types": "3.734.0",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.808.0.tgz",
+ "integrity": "sha512-9x2QWfphkARZY5OGkl9dJxZlSlYM2l5inFeo2bKntGuwg4A4YUe5h7d5yJ6sZbam9h43eBrkOdumx03DAkQF9A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/types": "^4.2.0",
"@smithy/util-config-provider": "^4.0.0",
- "@smithy/util-middleware": "^4.0.1",
+ "@smithy/util-middleware": "^4.0.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/s3-request-presigner": {
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.808.0.tgz",
+ "integrity": "sha512-viKWGrb7ZTN2rDkjX5rSkPeyKEVFDiyJS8HWVLBUJGwOLb65wluX+Rr/9fuCFyhCbBzhzpXFdzczZ0kCHOM6Qw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/signature-v4-multi-region": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@aws-sdk/util-format-url": "3.804.0",
+ "@smithy/middleware-endpoint": "^4.1.4",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/smithy-client": "^4.2.4",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -887,15 +987,16 @@
}
},
"node_modules/@aws-sdk/signature-v4-multi-region": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.758.0.tgz",
- "integrity": "sha512-0RPCo8fYJcrenJ6bRtiUbFOSgQ1CX/GpvwtLU2Fam1tS9h2klKK8d74caeV6A1mIUvBU7bhyQ0wMGlwMtn3EYw==",
- "dependencies": {
- "@aws-sdk/middleware-sdk-s3": "3.758.0",
- "@aws-sdk/types": "3.734.0",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/signature-v4": "^5.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.808.0.tgz",
+ "integrity": "sha512-lQuEB6JK81eKV7fdiktmRq06Y1KCcJbx9fLf7b19nSfYUbJSn/kfSpHPv/tOkJK2HKnN61JsfG19YU8k4SOU8Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/middleware-sdk-s3": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/signature-v4": "^5.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -903,15 +1004,16 @@
}
},
"node_modules/@aws-sdk/token-providers": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.758.0.tgz",
- "integrity": "sha512-ckptN1tNrIfQUaGWm/ayW1ddG+imbKN7HHhjFdS4VfItsP0QQOB0+Ov+tpgb4MoNR4JaUghMIVStjIeHN2ks1w==",
- "dependencies": {
- "@aws-sdk/nested-clients": "3.758.0",
- "@aws-sdk/types": "3.734.0",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/shared-ini-file-loader": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.808.0.tgz",
+ "integrity": "sha512-PsfKanHmnyO7FxowXqxbLQ+QjURCdSGxyhUiSdZbfvlvme/wqaMyIoMV/i4jppndksoSdPbW2kZXjzOqhQF+ew==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/nested-clients": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/shared-ini-file-loader": "^4.0.2",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -919,11 +1021,12 @@
}
},
"node_modules/@aws-sdk/types": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.734.0.tgz",
- "integrity": "sha512-o11tSPTT70nAkGV1fN9wm/hAIiLPyWX6SuGf+9JyTp7S/rC2cFWhR26MvA69nplcjNaXVzB0f+QFrLXXjOqCrg==",
+ "version": "3.804.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.804.0.tgz",
+ "integrity": "sha512-A9qnsy9zQ8G89vrPPlNG9d1d8QcKRGqJKqwyGgS0dclJpwy6d1EWgQLIolKPl6vcFpLoe6avLOLxr+h8ur5wpg==",
+ "license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -931,9 +1034,10 @@
}
},
"node_modules/@aws-sdk/util-arn-parser": {
- "version": "3.723.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.723.0.tgz",
- "integrity": "sha512-ZhEfvUwNliOQROcAk34WJWVYTlTa4694kSVhDSjW6lE1bMataPnIN8A0ycukEzBXmd8ZSoBcQLn6lKGl7XIJ5w==",
+ "version": "3.804.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.804.0.tgz",
+ "integrity": "sha512-wmBJqn1DRXnZu3b4EkE6CWnoWMo1ZMvlfkqU5zPz67xx1GMaXlDCchFvKAXMjk4jn/L1O3tKnoFDNsoLV1kgNQ==",
+ "license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
},
@@ -942,9 +1046,10 @@
}
},
"node_modules/@aws-sdk/util-dynamodb": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.758.0.tgz",
- "integrity": "sha512-JjBbhJLajilyMWJ/z82bYgIMj9XGISZ/QMYSpNBdzGFRmL1AL9s6NwLB6FuquRvpY9Lo3Y5vwEbedqdZPIrRFg==",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.808.0.tgz",
+ "integrity": "sha512-ydmqhKaT5rb2NClClbGRSjrW1kAJhgEMIP7B+drvhSBggMmTyTLrJCd9Be3Be9ce1oEXn03NbY1rcwtTusfdoA==",
+ "license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
},
@@ -952,17 +1057,33 @@
"node": ">=18.0.0"
},
"peerDependencies": {
- "@aws-sdk/client-dynamodb": "^3.758.0"
+ "@aws-sdk/client-dynamodb": "^3.808.0"
}
},
"node_modules/@aws-sdk/util-endpoints": {
- "version": "3.743.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.743.0.tgz",
- "integrity": "sha512-sN1l559zrixeh5x+pttrnd0A3+r34r0tmPkJ/eaaMaAzXqsmKU/xYre9K3FNnsSS1J1k4PEfk/nHDTVUgFYjnw==",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.808.0.tgz",
+ "integrity": "sha512-N6Lic98uc4ADB7fLWlzx+1uVnq04VgVjngZvwHoujcRg9YDhIg9dUDiTzD5VZv13g1BrPYmvYP1HhsildpGV6w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-endpoints": "^3.0.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-format-url": {
+ "version": "3.804.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.804.0.tgz",
+ "integrity": "sha512-1nOwSg7B0bj5LFGor0udF/HSdvDuSCxP+NC0IuSOJ5RgJ2AphFo03pLtK2UwArHY5WWZaejAEz5VBND6xxOEhA==",
+ "license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.734.0",
- "@smithy/types": "^4.1.0",
- "@smithy/util-endpoints": "^3.0.1",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/querystring-builder": "^4.0.2",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -970,9 +1091,10 @@
}
},
"node_modules/@aws-sdk/util-locate-window": {
- "version": "3.723.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.723.0.tgz",
- "integrity": "sha512-Yf2CS10BqK688DRsrKI/EO6B8ff5J86NXe4C+VCysK7UOgN0l1zOTeTukZ3H8Q9tYYX3oaF1961o8vRkFm7Nmw==",
+ "version": "3.804.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.804.0.tgz",
+ "integrity": "sha512-zVoRfpmBVPodYlnMjgVjfGoEZagyRF5IPn3Uo6ZvOZp24chnW/FRstH7ESDHDDRga4z3V+ElUQHKpFDXWyBW5A==",
+ "license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
},
@@ -981,25 +1103,27 @@
}
},
"node_modules/@aws-sdk/util-user-agent-browser": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.734.0.tgz",
- "integrity": "sha512-xQTCus6Q9LwUuALW+S76OL0jcWtMOVu14q+GoLnWPUM7QeUw963oQcLhF7oq0CtaLLKyl4GOUfcwc773Zmwwng==",
+ "version": "3.804.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.804.0.tgz",
+ "integrity": "sha512-KfW6T6nQHHM/vZBBdGn6fMyG/MgX5lq82TDdX4HRQRRuHKLgBWGpKXqqvBwqIaCdXwWHgDrg2VQups6GqOWW2A==",
+ "license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.734.0",
- "@smithy/types": "^4.1.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/types": "^4.2.0",
"bowser": "^2.11.0",
"tslib": "^2.6.2"
}
},
"node_modules/@aws-sdk/util-user-agent-node": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.758.0.tgz",
- "integrity": "sha512-A5EZw85V6WhoKMV2hbuFRvb9NPlxEErb4HPO6/SPXYY4QrjprIzScHxikqcWv1w4J3apB1wto9LPU3IMsYtfrw==",
- "dependencies": {
- "@aws-sdk/middleware-user-agent": "3.758.0",
- "@aws-sdk/types": "3.734.0",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "version": "3.808.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.808.0.tgz",
+ "integrity": "sha512-5UmB6u7RBSinXZAVP2iDgqyeVA/odO2SLEcrXaeTCw8ICXEoqF0K+GL36T4iDbzCBOAIugOZ6OcQX5vH3ck5UA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/middleware-user-agent": "3.808.0",
+ "@aws-sdk/types": "3.804.0",
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -1015,98 +1139,80 @@
}
},
"node_modules/@aws-sdk/xml-builder": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.734.0.tgz",
- "integrity": "sha512-Zrjxi5qwGEcUsJ0ru7fRtW74WcTS0rbLcehoFB+rN1GRi2hbLcFaYs4PwVA5diLeAJH0gszv3x4Hr/S87MfbKQ==",
+ "version": "3.804.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.804.0.tgz",
+ "integrity": "sha512-JbGWp36IG9dgxtvC6+YXwt5WDZYfuamWFtVfK6fQpnmL96dx+GUPOXPKRWdw67WLKf2comHY28iX2d3z35I53Q==",
+ "license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
}
},
- "node_modules/@babel/runtime": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.9.tgz",
- "integrity": "sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==",
+ "node_modules/@babel/code-frame": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "regenerator-runtime": "^0.14.0"
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
},
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@babel/runtime-corejs3": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.26.9.tgz",
- "integrity": "sha512-5EVjbTegqN7RSJle6hMWYxO4voo4rI+9krITk+DWR+diJgGrjZjrIBnJhjrHYYQsFgI7j1w1QnrvV7YSKBfYGg==",
- "dependencies": {
- "core-js-pure": "^3.30.2",
- "regenerator-runtime": "^0.14.0"
- },
+ "node_modules/@babel/compat-data": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz",
+ "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==",
+ "dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@eslint-community/eslint-utils": {
- "version": "4.5.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz",
- "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==",
+ "node_modules/@babel/core": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz",
+ "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==",
"dev": true,
- "dependencies": {
- "eslint-visitor-keys": "^3.4.3"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "license": "MIT",
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.27.1",
+ "@babel/helper-compilation-targets": "^7.27.1",
+ "@babel/helper-module-transforms": "^7.27.1",
+ "@babel/helpers": "^7.27.1",
+ "@babel/parser": "^7.27.1",
+ "@babel/template": "^7.27.1",
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
},
- "peerDependencies": {
- "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
- }
- },
- "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
- "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
- "dev": true,
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": ">=6.9.0"
},
"funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/@eslint-community/regexpp": {
- "version": "4.12.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
- "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
- "dev": true,
- "engines": {
- "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
- }
- },
- "node_modules/@eslint/config-array": {
- "version": "0.19.2",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz",
- "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==",
- "dev": true,
- "dependencies": {
- "@eslint/object-schema": "^2.1.6",
- "debug": "^4.3.1",
- "minimatch": "^3.1.2"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
}
},
- "node_modules/@eslint/config-array/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "node_modules/@babel/core/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
@@ -1119,2728 +1225,6309 @@
}
}
},
- "node_modules/@eslint/config-array/node_modules/ms": {
+ "node_modules/@babel/core/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/@eslint/config-helpers": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz",
- "integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==",
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
}
},
- "node_modules/@eslint/core": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz",
- "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==",
+ "node_modules/@babel/generator": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz",
+ "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@types/json-schema": "^7.0.15"
+ "@babel/parser": "^7.27.1",
+ "@babel/types": "^7.27.1",
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jsesc": "^3.0.2"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/@eslint/eslintrc": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz",
- "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==",
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
+ "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ajv": "^6.12.4",
- "debug": "^4.3.2",
- "espree": "^10.0.1",
- "globals": "^14.0.0",
- "ignore": "^5.2.0",
- "import-fresh": "^3.2.1",
- "js-yaml": "^4.1.0",
- "minimatch": "^3.1.2",
- "strip-json-comments": "^3.1.1"
+ "@babel/compat-data": "^7.27.2",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
},
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "engines": {
+ "node": ">=6.9.0"
}
},
- "node_modules/@eslint/eslintrc/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz",
+ "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ms": "^2.1.3"
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
},
"engines": {
- "node": ">=6.0"
+ "node": ">=6.9.0"
},
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@eslint/eslintrc/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true
- },
- "node_modules/@eslint/js": {
- "version": "9.23.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz",
- "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==",
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
+ "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/@eslint/object-schema": {
- "version": "2.1.6",
- "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
- "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/@eslint/plugin-kit": {
- "version": "0.2.7",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz",
- "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==",
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
+ "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
"dev": true,
- "dependencies": {
- "@eslint/core": "^0.12.0",
- "levn": "^0.4.1"
- },
+ "license": "MIT",
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/@humanfs/core": {
- "version": "0.19.1",
- "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
- "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=18.18.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/@humanfs/node": {
- "version": "0.16.6",
- "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
- "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
+ "node_modules/@babel/helpers": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz",
+ "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@humanfs/core": "^0.19.1",
- "@humanwhocodes/retry": "^0.3.0"
+ "@babel/template": "^7.27.1",
+ "@babel/types": "^7.27.1"
},
"engines": {
- "node": ">=18.18.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
- "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
+ "node_modules/@babel/parser": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz",
+ "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==",
"dev": true,
- "engines": {
- "node": ">=18.18"
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.27.1"
},
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/nzakas"
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
}
},
- "node_modules/@humanwhocodes/module-importer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
- "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
"dev": true,
- "engines": {
- "node": ">=12.22"
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
},
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/nzakas"
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@humanwhocodes/retry": {
- "version": "0.4.2",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz",
- "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==",
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
"dev": true,
- "engines": {
- "node": ">=18.18"
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
},
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/nzakas"
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@jsdevtools/ono": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
- "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="
- },
- "node_modules/@pm2/agent": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.4.tgz",
- "integrity": "sha512-n7WYvvTJhHLS2oBb1PjOtgLpMhgImOq8sXkPBw6smeg9LJBWZjiEgPKOpR8mn9UJZsB5P3W4V/MyvNnp31LKeA==",
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "async": "~3.2.0",
- "chalk": "~3.0.0",
- "dayjs": "~1.8.24",
- "debug": "~4.3.1",
- "eventemitter2": "~5.0.1",
- "fast-json-patch": "^3.0.0-1",
- "fclone": "~1.0.11",
- "nssocket": "0.6.0",
- "pm2-axon": "~4.0.1",
- "pm2-axon-rpc": "~0.7.0",
- "proxy-agent": "~6.3.0",
- "semver": "~7.5.0",
- "ws": "~7.5.10"
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@pm2/agent/node_modules/dayjs": {
- "version": "1.8.36",
- "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.36.tgz",
- "integrity": "sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw=="
- },
- "node_modules/@pm2/agent/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "ms": "^2.1.3"
+ "@babel/helper-plugin-utils": "^7.14.5"
},
"engines": {
- "node": ">=6.0"
+ "node": ">=6.9.0"
},
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@pm2/agent/node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "node_modules/@babel/plugin-syntax-import-attributes": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz",
+ "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "yallist": "^4.0.0"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
- "node": ">=10"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@pm2/agent/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
- },
- "node_modules/@pm2/agent/node_modules/semver": {
- "version": "7.5.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
- "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
+ "@babel/helper-plugin-utils": "^7.10.4"
},
- "engines": {
- "node": ">=10"
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@pm2/io": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/@pm2/io/-/io-6.0.1.tgz",
- "integrity": "sha512-KiA+shC6sULQAr9mGZ1pg+6KVW9MF8NpG99x26Lf/082/Qy8qsTCtnJy+HQReW1A9Rdf0C/404cz0RZGZro+IA==",
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "async": "~2.6.1",
- "debug": "~4.3.1",
- "eventemitter2": "^6.3.1",
- "require-in-the-middle": "^5.0.0",
- "semver": "~7.5.4",
- "shimmer": "^1.2.0",
- "signal-exit": "^3.0.3",
- "tslib": "1.9.3"
+ "@babel/helper-plugin-utils": "^7.8.0"
},
- "engines": {
- "node": ">=6.0"
- }
- },
- "node_modules/@pm2/io/node_modules/async": {
- "version": "2.6.4",
- "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
- "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
- "dependencies": {
- "lodash": "^4.17.14"
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@pm2/io/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz",
+ "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "ms": "^2.1.3"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
- "node": ">=6.0"
+ "node": ">=6.9.0"
},
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@pm2/io/node_modules/eventemitter2": {
- "version": "6.4.9",
- "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz",
- "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg=="
- },
- "node_modules/@pm2/io/node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "yallist": "^4.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
},
- "engines": {
- "node": ">=10"
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@pm2/io/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
- },
- "node_modules/@pm2/io/node_modules/semver": {
- "version": "7.5.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
- "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
+ "@babel/helper-plugin-utils": "^7.8.0"
},
- "engines": {
- "node": ">=10"
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@pm2/io/node_modules/tslib": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
- "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
- },
- "node_modules/@pm2/js-api": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/@pm2/js-api/-/js-api-0.8.0.tgz",
- "integrity": "sha512-nmWzrA/BQZik3VBz+npRcNIu01kdBhWL0mxKmP1ciF/gTcujPTQqt027N9fc1pK9ERM8RipFhymw7RcmCyOEYA==",
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "async": "^2.6.3",
- "debug": "~4.3.1",
- "eventemitter2": "^6.3.1",
- "extrareqp2": "^1.0.0",
- "ws": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
},
- "engines": {
- "node": ">=4.0"
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@pm2/js-api/node_modules/async": {
- "version": "2.6.4",
- "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
- "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "lodash": "^4.17.14"
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@pm2/js-api/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "ms": "^2.1.3"
+ "@babel/helper-plugin-utils": "^7.8.0"
},
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@pm2/js-api/node_modules/eventemitter2": {
- "version": "6.4.9",
- "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz",
- "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg=="
- },
- "node_modules/@pm2/js-api/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
- },
- "node_modules/@pm2/pm2-version-check": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@pm2/pm2-version-check/-/pm2-version-check-1.0.4.tgz",
- "integrity": "sha512-SXsM27SGH3yTWKc2fKR4SYNxsmnvuBQ9dd6QHtEWmiZ/VqaOYPAIlS8+vMcn27YLtAEBGvNRSh3TPNvtjZgfqA==",
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "debug": "^4.3.1"
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@pm2/pm2-version-check/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "ms": "^2.1.3"
+ "@babel/helper-plugin-utils": "^7.14.5"
},
"engines": {
- "node": ">=6.0"
+ "node": ">=6.9.0"
},
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@pm2/pm2-version-check/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
- },
- "node_modules/@scarf/scarf": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz",
- "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==",
- "hasInstallScript": true
- },
- "node_modules/@smithy/abort-controller": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz",
- "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==",
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
+ "@babel/helper-plugin-utils": "^7.14.5"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@smithy/chunked-blob-reader": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.0.0.tgz",
- "integrity": "sha512-+sKqDBQqb036hh4NPaUiEkYFkTUGYzRsn3EuFhyfQfMy6oGHEUJDurLP9Ufb5dasr/XiAmPNMr6wa9afjQB+Gw==",
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz",
+ "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "tslib": "^2.6.2"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@smithy/chunked-blob-reader-native": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.0.0.tgz",
- "integrity": "sha512-R9wM2yPmfEMsUmlMlIgSzOyICs0x9uu7UTHoccMyt7BWw8shcGM8HqB355+BZCPBcySvbTYMs62EgEQkNxz2ig==",
- "dependencies": {
- "@smithy/util-base64": "^4.0.0",
- "tslib": "^2.6.2"
- },
+ "node_modules/@babel/runtime": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz",
+ "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==",
+ "license": "MIT",
"engines": {
- "node": ">=18.0.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/@smithy/config-resolver": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.0.1.tgz",
- "integrity": "sha512-Igfg8lKu3dRVkTSEm98QpZUvKEOa71jDX4vKRcvJVyRc3UgN3j7vFMf0s7xLQhYmKa8kyJGQgUJDOV5V3neVlQ==",
+ "node_modules/@babel/runtime-corejs3": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.27.1.tgz",
+ "integrity": "sha512-909rVuj3phpjW6y0MCXAZ5iNeORePa6ldJvp2baWGcTjwqbBDDz6xoS5JHJ7lS88NlwLYj07ImL/8IUMtDZzTA==",
+ "license": "MIT",
"dependencies": {
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/util-config-provider": "^4.0.0",
- "@smithy/util-middleware": "^4.0.1",
- "tslib": "^2.6.2"
+ "core-js-pure": "^3.30.2"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/@smithy/core": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.5.tgz",
- "integrity": "sha512-HLclGWPkCsekQgsyzxLhCQLa8THWXtB5PxyYN+2O6nkyLt550KQKTlbV2D1/j5dNIQapAZM1+qFnpBFxZQkgCA==",
+ "node_modules/@babel/template": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
+ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/middleware-serde": "^4.0.2",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/util-body-length-browser": "^4.0.0",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-stream": "^4.1.2",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.2",
+ "@babel/types": "^7.27.1"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/@smithy/credential-provider-imds": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.1.tgz",
- "integrity": "sha512-l/qdInaDq1Zpznpmev/+52QomsJNZ3JkTl5yrTl02V6NBgJOQ4LY0SFw/8zsMwj3tLe8vqiIuwF6nxaEwgf6mg==",
+ "node_modules/@babel/traverse": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz",
+ "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/url-parser": "^4.0.1",
- "tslib": "^2.6.2"
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.27.1",
+ "@babel/parser": "^7.27.1",
+ "@babel/template": "^7.27.1",
+ "@babel/types": "^7.27.1",
+ "debug": "^4.3.1",
+ "globals": "^11.1.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/@smithy/eventstream-codec": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.1.tgz",
- "integrity": "sha512-Q2bCAAR6zXNVtJgifsU16ZjKGqdw/DyecKNgIgi7dlqw04fqDu0mnq+JmGphqheypVc64CYq3azSuCpAdFk2+A==",
+ "node_modules/@babel/traverse/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@aws-crypto/crc32": "5.2.0",
- "@smithy/types": "^4.1.0",
- "@smithy/util-hex-encoding": "^4.0.0",
- "tslib": "^2.6.2"
+ "ms": "^2.1.3"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/@smithy/eventstream-serde-browser": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.1.tgz",
- "integrity": "sha512-HbIybmz5rhNg+zxKiyVAnvdM3vkzjE6ccrJ620iPL8IXcJEntd3hnBl+ktMwIy12Te/kyrSbUb8UCdnUT4QEdA==",
- "dependencies": {
- "@smithy/eventstream-serde-universal": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
- },
+ "node_modules/@babel/traverse/node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=18.0.0"
+ "node": ">=4"
}
},
- "node_modules/@smithy/eventstream-serde-config-resolver": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.0.1.tgz",
- "integrity": "sha512-lSipaiq3rmHguHa3QFF4YcCM3VJOrY9oq2sow3qlhFY+nBSTF/nrO82MUQRPrxHQXA58J5G1UnU2WuJfi465BA==",
+ "node_modules/@babel/traverse/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@babel/types": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz",
+ "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/@smithy/eventstream-serde-node": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.1.tgz",
- "integrity": "sha512-o4CoOI6oYGYJ4zXo34U8X9szDe3oGjmHgsMGiZM0j4vtNoT+h80TLnkUcrLZR3+E6HIxqW+G+9WHAVfl0GXK0Q==",
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@es-joy/jsdoccomment": {
+ "version": "0.49.0",
+ "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz",
+ "integrity": "sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/eventstream-serde-universal": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
+ "comment-parser": "1.4.1",
+ "esquery": "^1.6.0",
+ "jsdoc-type-pratt-parser": "~4.1.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=16"
}
},
- "node_modules/@smithy/eventstream-serde-universal": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.1.tgz",
- "integrity": "sha512-Z94uZp0tGJuxds3iEAZBqGU2QiaBHP4YytLUjwZWx+oUeohCsLyUm33yp4MMBmhkuPqSbQCXq5hDet6JGUgHWA==",
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
+ "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/eventstream-codec": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
+ "eslint-visitor-keys": "^3.4.3"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
}
},
- "node_modules/@smithy/fetch-http-handler": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.1.tgz",
- "integrity": "sha512-3aS+fP28urrMW2KTjb6z9iFow6jO8n3MFfineGbndvzGZit3taZhKWtTorf+Gp5RpFDDafeHlhfsGlDCXvUnJA==",
- "dependencies": {
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/querystring-builder": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/util-base64": "^4.0.0",
- "tslib": "^2.6.2"
- },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">=18.0.0"
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/@smithy/hash-blob-browser": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.1.tgz",
- "integrity": "sha512-rkFIrQOKZGS6i1D3gKJ8skJ0RlXqDvb1IyAphksaFOMzkn3v3I1eJ8m7OkLj0jf1McP63rcCEoLlkAn/HjcTRw==",
- "dependencies": {
- "@smithy/chunked-blob-reader": "^5.0.0",
- "@smithy/chunked-blob-reader-native": "^4.0.0",
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
- },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=18.0.0"
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
},
- "node_modules/@smithy/hash-node": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.1.tgz",
- "integrity": "sha512-TJ6oZS+3r2Xu4emVse1YPB3Dq3d8RkZDKcPr71Nj/lJsdAP1c7oFzYqEn1IBc915TsgLl2xIJNuxCz+gLbLE0w==",
+ "node_modules/@eslint/config-array": {
+ "version": "0.20.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz",
+ "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==",
+ "dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
- "@smithy/util-buffer-from": "^4.0.0",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
+ "@eslint/object-schema": "^2.1.6",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@smithy/hash-stream-node": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.1.tgz",
- "integrity": "sha512-U1rAE1fxmReCIr6D2o/4ROqAQX+GffZpyMt3d7njtGDr2pUNmAKRWa49gsNVhCh2vVAuf3wXzWwNr2YN8PAXIw==",
+ "node_modules/@eslint/config-array/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/types": "^4.1.0",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
+ "ms": "^2.1.3"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/@smithy/invalid-dependency": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.1.tgz",
- "integrity": "sha512-gdudFPf4QRQ5pzj7HEnu6FhKRi61BfH/Gk5Yf6O0KiSbr1LlVhgjThcvjdu658VE6Nve8vaIWB8/fodmS1rBPQ==",
- "dependencies": {
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
- },
+ "node_modules/@eslint/config-array/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz",
+ "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==",
+ "dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">=18.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@smithy/is-array-buffer": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz",
- "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==",
+ "node_modules/@eslint/core": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz",
+ "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==",
+ "dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "tslib": "^2.6.2"
+ "@types/json-schema": "^7.0.15"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@smithy/md5-js": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.1.tgz",
- "integrity": "sha512-HLZ647L27APi6zXkZlzSFZIjpo8po45YiyjMGJZM3gyDY8n7dPGdmxIIljLm4gPt/7rRvutLTTkYJpZVfG5r+A==",
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
+ "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/types": "^4.1.0",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/@smithy/middleware-content-length": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.1.tgz",
- "integrity": "sha512-OGXo7w5EkB5pPiac7KNzVtfCW2vKBTZNuCctn++TTSOMpe6RZO/n6WEC1AxJINn3+vWLKW49uad3lo/u0WJ9oQ==",
+ "node_modules/@eslint/eslintrc/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
+ "ms": "^2.1.3"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/@smithy/middleware-endpoint": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.6.tgz",
- "integrity": "sha512-ftpmkTHIFqgaFugcjzLZv3kzPEFsBFSnq1JsIkr2mwFzCraZVhQk2gqN51OOeRxqhbPTkRFj39Qd2V91E/mQxg==",
- "dependencies": {
- "@smithy/core": "^3.1.5",
- "@smithy/middleware-serde": "^4.0.2",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/shared-ini-file-loader": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/url-parser": "^4.0.1",
- "@smithy/util-middleware": "^4.0.1",
- "tslib": "^2.6.2"
- },
+ "node_modules/@eslint/eslintrc/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.26.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.26.0.tgz",
+ "integrity": "sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=18.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@smithy/middleware-retry": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.7.tgz",
- "integrity": "sha512-58j9XbUPLkqAcV1kHzVX/kAR16GT+j7DUZJqwzsxh1jtz7G82caZiGyyFgUvogVfNTg3TeAOIJepGc8TXF4AVQ==",
- "dependencies": {
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/service-error-classification": "^4.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-retry": "^4.0.1",
- "tslib": "^2.6.2",
- "uuid": "^9.0.1"
- },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
+ "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
+ "dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">=18.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@smithy/middleware-serde": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.2.tgz",
- "integrity": "sha512-Sdr5lOagCn5tt+zKsaW+U2/iwr6bI9p08wOkCp6/eL6iMbgdtc2R5Ety66rf87PeohR0ExI84Txz9GYv5ou3iQ==",
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.2.8",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz",
+ "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==",
+ "dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
+ "@eslint/core": "^0.13.0",
+ "levn": "^0.4.1"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@smithy/middleware-stack": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.1.tgz",
- "integrity": "sha512-dHwDmrtR/ln8UTHpaIavRSzeIk5+YZTBtLnKwDW3G2t6nAupCiQUvNzNoHBpik63fwUaJPtlnMzXbQrNFWssIA==",
+ "node_modules/@fast-csv/format": {
+ "version": "4.3.5",
+ "resolved": "https://registry.npmjs.org/@fast-csv/format/-/format-4.3.5.tgz",
+ "integrity": "sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==",
+ "license": "MIT",
"dependencies": {
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
+ "@types/node": "^14.0.1",
+ "lodash.escaperegexp": "^4.1.2",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isequal": "^4.5.0",
+ "lodash.isfunction": "^3.0.9",
+ "lodash.isnil": "^4.0.0"
}
},
- "node_modules/@smithy/node-config-provider": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz",
- "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==",
+ "node_modules/@fast-csv/format/node_modules/@types/node": {
+ "version": "14.18.63",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz",
+ "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==",
+ "license": "MIT"
+ },
+ "node_modules/@fast-csv/parse": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/@fast-csv/parse/-/parse-4.3.6.tgz",
+ "integrity": "sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==",
+ "license": "MIT",
"dependencies": {
- "@smithy/property-provider": "^4.0.1",
- "@smithy/shared-ini-file-loader": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
- },
+ "@types/node": "^14.0.1",
+ "lodash.escaperegexp": "^4.1.2",
+ "lodash.groupby": "^4.6.0",
+ "lodash.isfunction": "^3.0.9",
+ "lodash.isnil": "^4.0.0",
+ "lodash.isundefined": "^3.0.1",
+ "lodash.uniq": "^4.5.0"
+ }
+ },
+ "node_modules/@fast-csv/parse/node_modules/@types/node": {
+ "version": "14.18.63",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz",
+ "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==",
+ "license": "MIT"
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">=18.0.0"
+ "node": ">=18.18.0"
}
},
- "node_modules/@smithy/node-http-handler": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.3.tgz",
- "integrity": "sha512-dYCLeINNbYdvmMLtW0VdhW1biXt+PPCGazzT5ZjKw46mOtdgToQEwjqZSS9/EN8+tNs/RO0cEWG044+YZs97aA==",
+ "node_modules/@humanfs/node": {
+ "version": "0.16.6",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
+ "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
+ "dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@smithy/abort-controller": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/querystring-builder": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.3.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=18.18.0"
}
},
- "node_modules/@smithy/property-provider": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.1.tgz",
- "integrity": "sha512-o+VRiwC2cgmk/WFV0jaETGOtX16VNPp2bSQEzu0whbReqE1BMqsP2ami2Vi3cbGVdKu1kq9gQkDAGKbt0WOHAQ==",
- "dependencies": {
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
- },
+ "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
+ "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
+ "dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">=18.0.0"
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
}
},
- "node_modules/@smithy/protocol-http": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz",
- "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==",
- "dependencies": {
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
},
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">=18.0.0"
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
}
},
- "node_modules/@smithy/querystring-builder": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz",
- "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==",
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "license": "ISC",
"dependencies": {
- "@smithy/types": "^4.1.0",
- "@smithy/util-uri-escape": "^4.0.0",
- "tslib": "^2.6.2"
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=8"
}
},
- "node_modules/@smithy/querystring-parser": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.1.tgz",
- "integrity": "sha512-Ma2XC7VS9aV77+clSFylVUnPZRindhB7BbmYiNOdr+CHt/kZNJoPP0cd3QxCnCFyPXC4eybmyE98phEHkqZ5Jw==",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
+ "sprintf-js": "~1.0.2"
}
},
- "node_modules/@smithy/service-error-classification": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.1.tgz",
- "integrity": "sha512-3JNjBfOWpj/mYfjXJHB4Txc/7E4LVq32bwzE7m28GN79+M1f76XHflUaSUkhOriprPDzev9cX/M+dEB80DNDKA==",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/types": "^4.1.0"
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=8"
}
},
- "node_modules/@smithy/shared-ini-file-loader": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.1.tgz",
- "integrity": "sha512-hC8F6qTBbuHRI/uqDgqqi6J0R4GtEZcgrZPhFQnMhfJs3MnUTGSnR1NSJCJs5VWlMydu0kJz15M640fJlRsIOw==",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
},
- "engines": {
- "node": ">=18.0.0"
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/@smithy/signature-v4": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.0.1.tgz",
- "integrity": "sha512-nCe6fQ+ppm1bQuw5iKoeJ0MJfz2os7Ic3GBjOkLOPtavbD1ONoyE3ygjBfz2ythFWm4YnRm6OxW+8p/m9uCoIA==",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/is-array-buffer": "^4.0.0",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/util-hex-encoding": "^4.0.0",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-uri-escape": "^4.0.0",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
+ "p-locate": "^4.1.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=8"
}
},
- "node_modules/@smithy/smithy-client": {
- "version": "4.1.6",
- "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.6.tgz",
- "integrity": "sha512-UYDolNg6h2O0L+cJjtgSyKKvEKCOa/8FHYJnBobyeoeWDmNpXjwOAtw16ezyeu1ETuuLEOZbrynK0ZY1Lx9Jbw==",
- "dependencies": {
- "@smithy/core": "^3.1.5",
- "@smithy/middleware-endpoint": "^4.0.6",
- "@smithy/middleware-stack": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/util-stream": "^4.1.2",
- "tslib": "^2.6.2"
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@smithy/types": {
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
"version": "4.1.0",
- "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz",
- "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "tslib": "^2.6.2"
+ "p-limit": "^2.2.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=8"
}
},
- "node_modules/@smithy/url-parser": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.1.tgz",
- "integrity": "sha512-gPXcIEUtw7VlK8f/QcruNXm7q+T5hhvGu9tl63LsJPZ27exB6dtNwvh2HIi0v7JcXJ5emBxB+CJxwaLEdJfA+g==",
- "dependencies": {
- "@smithy/querystring-parser": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
- },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=18.0.0"
+ "node": ">=8"
}
},
- "node_modules/@smithy/util-base64": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz",
- "integrity": "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==",
- "dependencies": {
- "@smithy/util-buffer-from": "^4.0.0",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
- },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=18.0.0"
+ "node": ">=8"
}
},
- "node_modules/@smithy/util-body-length-browser": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz",
- "integrity": "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==",
+ "node_modules/@jest/console": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
+ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "tslib": "^2.6.2"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@smithy/util-body-length-node": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz",
- "integrity": "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==",
- "dependencies": {
- "tslib": "^2.6.2"
+ "node_modules/@jest/core": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
+ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/reporters": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-changed-files": "^29.7.0",
+ "jest-config": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-resolve-dependencies": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
},
- "engines": {
- "node": ">=18.0.0"
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
}
},
- "node_modules/@smithy/util-buffer-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz",
- "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==",
+ "node_modules/@jest/environment": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/is-array-buffer": "^4.0.0",
- "tslib": "^2.6.2"
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@smithy/util-config-provider": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz",
- "integrity": "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==",
+ "node_modules/@jest/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "tslib": "^2.6.2"
+ "expect": "^29.7.0",
+ "jest-snapshot": "^29.7.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@smithy/util-defaults-mode-browser": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.7.tgz",
- "integrity": "sha512-CZgDDrYHLv0RUElOsmZtAnp1pIjwDVCSuZWOPhIOBvG36RDfX1Q9+6lS61xBf+qqvHoqRjHxgINeQz47cYFC2Q==",
+ "node_modules/@jest/expect-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
+ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/property-provider": "^4.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
- "bowser": "^2.11.0",
- "tslib": "^2.6.2"
+ "jest-get-type": "^29.6.3"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@smithy/util-defaults-mode-node": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.7.tgz",
- "integrity": "sha512-79fQW3hnfCdrfIi1soPbK3zmooRFnLpSx3Vxi6nUlqaaQeC5dm8plt4OTNDNqEEEDkvKghZSaoti684dQFVrGQ==",
- "dependencies": {
- "@smithy/config-resolver": "^4.0.1",
- "@smithy/credential-provider-imds": "^4.0.1",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
+ "node_modules/@jest/fake-timers": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@smithy/util-endpoints": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.1.tgz",
- "integrity": "sha512-zVdUENQpdtn9jbpD9SCFK4+aSiavRb9BxEtw9ZGUR1TYo6bBHbIoi7VkrFQ0/RwZlzx0wRBaRmPclj8iAoJCLA==",
+ "node_modules/@jest/globals": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
+ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "jest-mock": "^29.7.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@smithy/util-hex-encoding": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz",
- "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==",
+ "node_modules/@jest/reporters": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
+ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^6.0.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.1",
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "tslib": "^2.6.2"
+ "@sinclair/typebox": "^0.27.8"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@smithy/util-middleware": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.1.tgz",
- "integrity": "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==",
+ "node_modules/@jest/source-map": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
+ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.9"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@smithy/util-retry": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.1.tgz",
- "integrity": "sha512-WmRHqNVwn3kI3rKk1LsKcVgPBG6iLTBGC1iYOV3GQegwJ3E8yjzHytPt26VNzOWr1qu0xE03nK0Ug8S7T7oufw==",
+ "node_modules/@jest/test-result": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
+ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/service-error-classification": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
+ "@jest/console": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@smithy/util-stream": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.1.2.tgz",
- "integrity": "sha512-44PKEqQ303d3rlQuiDpcCcu//hV8sn+u2JBo84dWCE0rvgeiVl0IlLMagbU++o0jCWhYCsHaAt9wZuZqNe05Hw==",
+ "node_modules/@jest/test-sequencer": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
+ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/fetch-http-handler": "^5.0.1",
- "@smithy/node-http-handler": "^4.0.3",
- "@smithy/types": "^4.1.0",
- "@smithy/util-base64": "^4.0.0",
- "@smithy/util-buffer-from": "^4.0.0",
- "@smithy/util-hex-encoding": "^4.0.0",
- "@smithy/util-utf8": "^4.0.0",
- "tslib": "^2.6.2"
+ "@jest/test-result": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "slash": "^3.0.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@smithy/util-uri-escape": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz",
- "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==",
+ "node_modules/@jest/transform": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "tslib": "^2.6.2"
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@smithy/util-utf8": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz",
- "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==",
+ "node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/util-buffer-from": "^4.0.0",
- "tslib": "^2.6.2"
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@smithy/util-waiter": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.2.tgz",
- "integrity": "sha512-piUTHyp2Axx3p/kc2CIJkYSv0BAaheBQmbACZgQSSfWUumWNW+R1lL+H9PDBxKJkvOeEX+hKYEFiwO8xagL8AQ==",
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
+ "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@smithy/abort-controller": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "tslib": "^2.6.2"
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=6.0.0"
}
},
- "node_modules/@swagger-api/apidom-ast": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ast/-/apidom-ast-1.0.0-beta.12.tgz",
- "integrity": "sha512-KdJ+8PyYvfnHgpqrC0WWDRJLVx6+YkmYgAGpsdOa8S/p6btJdCUozeqpcXawmGqwAX/9jCXbmKdia3v3fUrP0w==",
- "dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-error": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "unraw": "^3.0.0"
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
}
},
- "node_modules/@swagger-api/apidom-core": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-core/-/apidom-core-1.0.0-beta.12.tgz",
- "integrity": "sha512-CAr6aSk9l9ZJUneHpmwk4Br0NZhFLy2QRHoPmr2pWMlAn+0YC4eRYtwOEB8PVsCmP83D4MiXU5zi6cOZyV/cVw==",
- "dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-ast": "^1.0.0-beta.12",
- "@swagger-api/apidom-error": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "minim": "~0.23.8",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "short-unique-id": "^5.0.2",
- "ts-mixer": "^6.0.3"
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
}
},
- "node_modules/@swagger-api/apidom-error": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-error/-/apidom-error-1.0.0-beta.12.tgz",
- "integrity": "sha512-p74a/8GgitGIYvjD5WmROEHv2bGCnDKug3QpJvC5+g36ErZQp428+fK5hhfKQuCo0rjD2fZvs27S17Zh8y0zFw==",
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7"
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
}
},
- "node_modules/@swagger-api/apidom-json-pointer": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-json-pointer/-/apidom-json-pointer-1.0.0-beta.12.tgz",
- "integrity": "sha512-JuCqMVfDSWJ7JcdPjYgGjNlqjmKQwxuQh7uKKBLTpNccmXYT+x7WemPuzcWjVVHDd5plw8yQ0YvaU0HlqjS1mA==",
+ "node_modules/@jsdevtools/ono": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
+ "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
+ "license": "MIT"
+ },
+ "node_modules/@modelcontextprotocol/sdk": {
+ "version": "1.11.2",
+ "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.2.tgz",
+ "integrity": "sha512-H9vwztj5OAqHg9GockCQC06k1natgcxWQSRpQcPJf6i5+MWBzfKkRtxGbjQf0X2ihii0ffLZCRGbYV2f2bjNCQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-error": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0"
+ "content-type": "^1.0.5",
+ "cors": "^2.8.5",
+ "cross-spawn": "^7.0.3",
+ "eventsource": "^3.0.2",
+ "express": "^5.0.1",
+ "express-rate-limit": "^7.5.0",
+ "pkce-challenge": "^5.0.0",
+ "raw-body": "^3.0.0",
+ "zod": "^3.23.8",
+ "zod-to-json-schema": "^3.24.1"
+ },
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@swagger-api/apidom-ns-api-design-systems": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-api-design-systems/-/apidom-ns-api-design-systems-1.0.0-beta.12.tgz",
- "integrity": "sha512-D4MAnm1Jiame1KfxkboYU/gRsvlDaplFE3SGjdg/dG3vTOHWXzm5ta8pEf3naPuo8+fXt0rcMxf2edaFHnPLWA==",
- "optional": true,
+ "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
+ "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-error": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-openapi-3-1": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "ts-mixer": "^6.0.3"
+ "mime-types": "^3.0.0",
+ "negotiator": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
}
},
- "node_modules/@swagger-api/apidom-ns-asyncapi-2": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-asyncapi-2/-/apidom-ns-asyncapi-2-1.0.0-beta.12.tgz",
- "integrity": "sha512-3R1AdZdUNo2rw9PudkWfP0f556DFTjUn9mBdbLHQPhcmdIRTJQAMDNy2FhN6ZiEg4ggG31Hyk2AY/97CAxHd6A==",
- "optional": true,
+ "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
+ "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-json-schema-draft-7": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "ts-mixer": "^6.0.3"
+ "bytes": "^3.1.2",
+ "content-type": "^1.0.5",
+ "debug": "^4.4.0",
+ "http-errors": "^2.0.0",
+ "iconv-lite": "^0.6.3",
+ "on-finished": "^2.4.1",
+ "qs": "^6.14.0",
+ "raw-body": "^3.0.0",
+ "type-is": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@swagger-api/apidom-ns-json-schema-2019-09": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-2019-09/-/apidom-ns-json-schema-2019-09-1.0.0-beta.12.tgz",
- "integrity": "sha512-mrcWwAfCcUDiPrGymowZqnrOpOk7hUNDkW9WjsMe3bFiTrCm4EsQYvGtyWAtB/0yo7hNBMGXYEtDWfGBsw8AyA==",
- "dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-error": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-json-schema-draft-7": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "ts-mixer": "^6.0.4"
+ "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
+ "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
}
},
- "node_modules/@swagger-api/apidom-ns-json-schema-2020-12": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-2020-12/-/apidom-ns-json-schema-2020-12-1.0.0-beta.12.tgz",
- "integrity": "sha512-SW0Jtty3o12OwpTAVJEewurvTSIhxJ72TZlMSk5L36jvekzqKfLL7aBYRCEE9QkV3rxTjxOf0WK/tYLRMKUbzw==",
- "dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-error": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-json-schema-2019-09": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "ts-mixer": "^6.0.4"
+ "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
+ "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.6.0"
}
},
- "node_modules/@swagger-api/apidom-ns-json-schema-draft-4": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-4/-/apidom-ns-json-schema-draft-4-1.0.0-beta.12.tgz",
- "integrity": "sha512-Z3PnEEdkGnr6zomFAgmkkDGrwlj3bbbEJBfXsshxRuXf3i5RymiURFy42CfKa5Tmx3rw8rSw393p0TkHqS0NIg==",
+ "node_modules/@modelcontextprotocol/sdk/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-ast": "^1.0.0-beta.12",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "ts-mixer": "^6.0.4"
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/@swagger-api/apidom-ns-json-schema-draft-6": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-6/-/apidom-ns-json-schema-draft-6-1.0.0-beta.12.tgz",
- "integrity": "sha512-QvubeYZvRd19Q8VVP4xGGYTuSVgLQqEp/epe8LXcrFJvgF6A9CTUxkfKVxL4+Q5a9DFaKTZKNYwkRaPzisvnWQ==",
- "dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-error": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-json-schema-draft-4": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "ts-mixer": "^6.0.4"
+ "node_modules/@modelcontextprotocol/sdk/node_modules/express": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
+ "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "^2.0.0",
+ "body-parser": "^2.2.0",
+ "content-disposition": "^1.0.0",
+ "content-type": "^1.0.5",
+ "cookie": "^0.7.1",
+ "cookie-signature": "^1.2.1",
+ "debug": "^4.4.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "finalhandler": "^2.1.0",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.0",
+ "merge-descriptors": "^2.0.0",
+ "mime-types": "^3.0.0",
+ "on-finished": "^2.4.1",
+ "once": "^1.4.0",
+ "parseurl": "^1.3.3",
+ "proxy-addr": "^2.0.7",
+ "qs": "^6.14.0",
+ "range-parser": "^1.2.1",
+ "router": "^2.2.0",
+ "send": "^1.1.0",
+ "serve-static": "^2.2.0",
+ "statuses": "^2.0.1",
+ "type-is": "^2.0.1",
+ "vary": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
- "node_modules/@swagger-api/apidom-ns-json-schema-draft-7": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-7/-/apidom-ns-json-schema-draft-7-1.0.0-beta.12.tgz",
- "integrity": "sha512-UIU/vY5xBhYeBEykmXMvQRaIXqWWNWc/RPG5L8LrfILoZhzZbjqcdRMf5w4wQWqteQxXxkpDdkcHVBsJxcQtJg==",
- "dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-error": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-json-schema-draft-6": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "ts-mixer": "^6.0.4"
+ "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz",
+ "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "on-finished": "^2.4.1",
+ "parseurl": "^1.3.3",
+ "statuses": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
}
},
- "node_modules/@swagger-api/apidom-ns-openapi-2": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-2/-/apidom-ns-openapi-2-1.0.0-beta.12.tgz",
- "integrity": "sha512-61I3NcH2agyPmNXW7JOoxshjVr7YVekHnEaYfl3VYTc0mT2KcRhcDWM0cufQdGeIJPR9SdFcSZ01aRQUUTj3fQ==",
- "optional": true,
- "dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-error": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-json-schema-draft-4": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "ts-mixer": "^6.0.3"
+ "node_modules/@modelcontextprotocol/sdk/node_modules/fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
+ "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
}
},
- "node_modules/@swagger-api/apidom-ns-openapi-3-0": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-0/-/apidom-ns-openapi-3-0-1.0.0-beta.12.tgz",
- "integrity": "sha512-6TWUagR1/Y9HB8t75/vrkHHDV5c5K0S72Wywx7PoDyNgQ1Jxy3p6iwuSHfTwJYH+/hAxg3f91i6HXXyrHB5RAg==",
- "dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-error": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-json-schema-draft-4": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "ts-mixer": "^6.0.3"
+ "node_modules/@modelcontextprotocol/sdk/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "node_modules/@swagger-api/apidom-ns-openapi-3-1": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-1/-/apidom-ns-openapi-3-1-1.0.0-beta.12.tgz",
- "integrity": "sha512-IayaLSawWo5rAyM2nRY6faTfK8cJQ+mGGR94NOmsjcUQw9IljY9uX7PXj3izOdFlXFYjgR1P+mIhuuXyDuw4qg==",
- "dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-ast": "^1.0.0-beta.12",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-json-pointer": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-json-schema-2020-12": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-openapi-3-0": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "ts-mixer": "^6.0.3"
+ "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
+ "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
}
},
- "node_modules/@swagger-api/apidom-ns-workflows-1": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-workflows-1/-/apidom-ns-workflows-1-1.0.0-beta.12.tgz",
- "integrity": "sha512-ALQbORmsql7HJjlCWMzOfTIqc0O0gCJbp3je+uzp2Y3Cu2BlQgu7aZAGly+GdM1rWNJosm0ZOGG1KTfgJaTZxw==",
- "optional": true,
- "dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-json-schema-2020-12": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "ts-mixer": "^6.0.3"
+ "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
+ "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-json": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-json/-/apidom-parser-adapter-api-design-systems-json-1.0.0-beta.12.tgz",
- "integrity": "sha512-DjFZmSmoMmSu9gHWcpWGuaZd5o2eD5xkhHwL2QjvFvH7UXBxxhrx89RwNmHt1Hy5De4fV+zlB/7TsL7FsV4i8Q==",
- "optional": true,
- "dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-api-design-systems": "^1.0.0-beta.12",
- "@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0"
+ "node_modules/@modelcontextprotocol/sdk/node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-yaml": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/-/apidom-parser-adapter-api-design-systems-yaml-1.0.0-beta.12.tgz",
- "integrity": "sha512-bWJ0KylVPNeAqI/KPqaT1PfmIlWFx7fY5MBsIccn9iSB880oUSB+XLmIRpFBOSh5iPM7Dn6GTg3gdnVJRk5fNA==",
- "optional": true,
+ "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
+ "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-api-design-systems": "^1.0.0-beta.12",
- "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0"
+ "mime-db": "^1.54.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-json-2": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-json-2/-/apidom-parser-adapter-asyncapi-json-2-1.0.0-beta.12.tgz",
- "integrity": "sha512-UAbPIKHNYUy4MOWGyPSkafgipX0zwndSidqG9AUzeDe4t5yldnBRPnCTnUHecSqktIzq5Tz6mViNTc1/uY9lOg==",
- "optional": true,
- "dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-asyncapi-2": "^1.0.0-beta.12",
- "@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0"
+ "node_modules/@modelcontextprotocol/sdk/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
+ "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/-/apidom-parser-adapter-asyncapi-yaml-2-1.0.0-beta.12.tgz",
- "integrity": "sha512-gT6Z2ReDxELPE6ZzDxf/wQM+AcG13eXGLDcYTOOKacBruWsh8Aa/iF9ZW0DlJckE+vlDgvbhlkxsiHIExOY41g==",
- "optional": true,
+ "node_modules/@modelcontextprotocol/sdk/node_modules/qs": {
+ "version": "6.14.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
+ "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
+ "dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-asyncapi-2": "^1.0.0-beta.12",
- "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0"
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-json": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-json/-/apidom-parser-adapter-json-1.0.0-beta.12.tgz",
- "integrity": "sha512-Bt7oCylNzf49MRsnnWayIqh2QBIVRGq35k/dcmb0J8QP94GDLfbOCXn0kvuRJvQIK/aJFlBFVMVn47GKQibqfg==",
- "optional": true,
+ "node_modules/@modelcontextprotocol/sdk/node_modules/raw-body": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
+ "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-ast": "^1.0.0-beta.12",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-error": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "tree-sitter": "=0.22.1",
- "tree-sitter-json": "=0.24.8",
- "web-tree-sitter": "=0.24.5"
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.6.3",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-json/node_modules/tree-sitter": {
- "version": "0.22.1",
- "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.22.1.tgz",
- "integrity": "sha512-gRO+jk2ljxZlIn20QRskIvpLCMtzuLl5T0BY6L9uvPYD17uUrxlxWkvYCiVqED2q2q7CVtY52Uex4WcYo2FEXw==",
- "hasInstallScript": true,
- "optional": true,
+ "node_modules/@modelcontextprotocol/sdk/node_modules/send": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
+ "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "node-addon-api": "^8.2.1",
- "node-gyp-build": "^4.8.2"
+ "debug": "^4.3.5",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.0",
+ "mime-types": "^3.0.1",
+ "ms": "^2.1.3",
+ "on-finished": "^2.4.1",
+ "range-parser": "^1.2.1",
+ "statuses": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 18"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-2": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-2/-/apidom-parser-adapter-openapi-json-2-1.0.0-beta.12.tgz",
- "integrity": "sha512-zMrLeDvDOCGgMNYMW9iuAlOtA+mCa4msBM70tgVdg/89SdS4K5MxVptmpRHQAODdv1oErm2ChVmzFcuPHH38qw==",
- "optional": true,
+ "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
+ "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-openapi-2": "^1.0.0-beta.12",
- "@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0"
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "parseurl": "^1.3.3",
+ "send": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 18"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-0": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-0/-/apidom-parser-adapter-openapi-json-3-0-1.0.0-beta.12.tgz",
- "integrity": "sha512-tJznOQ+8iEOfKU01hLt6FHLgsRfd5zugnNFuNTvS7oJt6xtQ9vqFS/uKajMSOq6p+irAF6dWI+C5f+1AdDOvnw==",
- "optional": true,
+ "node_modules/@modelcontextprotocol/sdk/node_modules/type-is": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
+ "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-openapi-3-0": "^1.0.0-beta.12",
- "@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0"
+ "content-type": "^1.0.5",
+ "media-typer": "^1.1.0",
+ "mime-types": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-1": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-1/-/apidom-parser-adapter-openapi-json-3-1-1.0.0-beta.12.tgz",
- "integrity": "sha512-HLToO8Jqo06p70h3MWA2FkkNSfRi2M9fjNW3V94nCb6ECMIfgppgw+FDwawskvBNH6RfZqN7OBgq19Vly/sgbw==",
- "optional": true,
- "dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-openapi-3-1": "^1.0.0-beta.12",
- "@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0"
+ "node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-2": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-2/-/apidom-parser-adapter-openapi-yaml-2-1.0.0-beta.12.tgz",
- "integrity": "sha512-mdg1/80lkoMVla3rvH7GeIuyj70YONJ3CnnBKJ/FIsFjgAViiC3mT5UnP6HmNQ+ZhAl1IvTmkdeI4GQsNtuW/g==",
- "optional": true,
+ "node_modules/@paralleldrive/cuid2": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz",
+ "integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==",
+ "license": "MIT",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-openapi-2": "^1.0.0-beta.12",
- "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0"
+ "@noble/hashes": "^1.1.5"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/-/apidom-parser-adapter-openapi-yaml-3-0-1.0.0-beta.12.tgz",
- "integrity": "sha512-vUgsJjoItuL+6yOxAFzuMEdPsL3qzwvqZnlwXSPXyCdnzrChzfmWM083LvxyyuQQaBRAhzoYcxSsavZq9MQuUg==",
- "optional": true,
+ "node_modules/@pm2/agent": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.4.tgz",
+ "integrity": "sha512-n7WYvvTJhHLS2oBb1PjOtgLpMhgImOq8sXkPBw6smeg9LJBWZjiEgPKOpR8mn9UJZsB5P3W4V/MyvNnp31LKeA==",
+ "license": "AGPL-3.0",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-openapi-3-0": "^1.0.0-beta.12",
- "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0"
+ "async": "~3.2.0",
+ "chalk": "~3.0.0",
+ "dayjs": "~1.8.24",
+ "debug": "~4.3.1",
+ "eventemitter2": "~5.0.1",
+ "fast-json-patch": "^3.0.0-1",
+ "fclone": "~1.0.11",
+ "nssocket": "0.6.0",
+ "pm2-axon": "~4.0.1",
+ "pm2-axon-rpc": "~0.7.0",
+ "proxy-agent": "~6.3.0",
+ "semver": "~7.5.0",
+ "ws": "~7.5.10"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/-/apidom-parser-adapter-openapi-yaml-3-1-1.0.0-beta.12.tgz",
- "integrity": "sha512-HHKxKrs99UZmymMScnyEz8VYwicJj78H0iLsuYjIJDggtvKx/kHxTM16/vAe9et7q/uP+BqP/hyUKNeS7n23Kw==",
- "optional": true,
+ "node_modules/@pm2/agent/node_modules/chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "license": "MIT",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-openapi-3-1": "^1.0.0-beta.12",
- "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0"
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-workflows-json-1": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-workflows-json-1/-/apidom-parser-adapter-workflows-json-1-1.0.0-beta.12.tgz",
- "integrity": "sha512-soKD4N7JUvgiPRdsWGJ53itp5mcueoSvb6ikcMneEOu9wxL3y40aCK5Vb76UuVKRZmqWRXpgs3kl5oL34Bno9Q==",
- "optional": true,
+ "node_modules/@pm2/agent/node_modules/dayjs": {
+ "version": "1.8.36",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.36.tgz",
+ "integrity": "sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==",
+ "license": "MIT"
+ },
+ "node_modules/@pm2/agent/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "license": "MIT",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-workflows-1": "^1.0.0-beta.12",
- "@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0"
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-workflows-yaml-1": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-workflows-yaml-1/-/apidom-parser-adapter-workflows-yaml-1-1.0.0-beta.12.tgz",
- "integrity": "sha512-+1GZknZH3shdViUubKTCOolZzday+h3Cxp9PQDb8LgGJcxu40HHf44YZdZNsmkDLXqd2t7+NGbt2EXum7CTgtA==",
- "optional": true,
+ "node_modules/@pm2/agent/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "license": "ISC",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-ns-workflows-1": "^1.0.0-beta.12",
- "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0"
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-yaml-1-2": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-yaml-1-2/-/apidom-parser-adapter-yaml-1-2-1.0.0-beta.12.tgz",
- "integrity": "sha512-SP5Sz1ywsW3vZxrl+/NBGDNvP/rZJ8tm8+0OQJ+HISwcpwSR92rYDUEYBuuxPX1Bw4c1V0UkQqqEVf59NksCsQ==",
- "optional": true,
+ "node_modules/@pm2/agent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/@pm2/agent/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "license": "ISC",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-ast": "^1.0.0-beta.12",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@swagger-api/apidom-error": "^1.0.0-beta.12",
- "@tree-sitter-grammars/tree-sitter-yaml": "=0.7.0",
- "@types/ramda": "~0.30.0",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0",
- "tree-sitter": "=0.22.1",
- "web-tree-sitter": "=0.24.5"
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-yaml-1-2/node_modules/@tree-sitter-grammars/tree-sitter-yaml": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/@tree-sitter-grammars/tree-sitter-yaml/-/tree-sitter-yaml-0.7.0.tgz",
- "integrity": "sha512-GOMIK3IaDvECD0eZEhAsLl03RMtM1E8StxuGMn6PpMKFg7jyQ+jSzxJZ4Jmc/tYitah9/AECt8o4tlRQ5yEZQg==",
- "hasInstallScript": true,
- "optional": true,
+ "node_modules/@pm2/agent/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "license": "ISC"
+ },
+ "node_modules/@pm2/io": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/@pm2/io/-/io-6.0.1.tgz",
+ "integrity": "sha512-KiA+shC6sULQAr9mGZ1pg+6KVW9MF8NpG99x26Lf/082/Qy8qsTCtnJy+HQReW1A9Rdf0C/404cz0RZGZro+IA==",
+ "license": "Apache-2",
"dependencies": {
- "node-addon-api": "^8.3.0",
- "node-gyp-build": "^4.8.4"
+ "async": "~2.6.1",
+ "debug": "~4.3.1",
+ "eventemitter2": "^6.3.1",
+ "require-in-the-middle": "^5.0.0",
+ "semver": "~7.5.4",
+ "shimmer": "^1.2.0",
+ "signal-exit": "^3.0.3",
+ "tslib": "1.9.3"
},
- "peerDependencies": {
- "tree-sitter": "^0.22.1"
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
+ "node_modules/@pm2/io/node_modules/async": {
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
+ "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
+ "license": "MIT",
+ "dependencies": {
+ "lodash": "^4.17.14"
+ }
+ },
+ "node_modules/@pm2/io/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
},
"peerDependenciesMeta": {
- "tree-sitter": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@pm2/io/node_modules/eventemitter2": {
+ "version": "6.4.9",
+ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz",
+ "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==",
+ "license": "MIT"
+ },
+ "node_modules/@pm2/io/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@pm2/io/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/@pm2/io/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "license": "ISC",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@pm2/io/node_modules/tslib": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@pm2/io/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "license": "ISC"
+ },
+ "node_modules/@pm2/js-api": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@pm2/js-api/-/js-api-0.8.0.tgz",
+ "integrity": "sha512-nmWzrA/BQZik3VBz+npRcNIu01kdBhWL0mxKmP1ciF/gTcujPTQqt027N9fc1pK9ERM8RipFhymw7RcmCyOEYA==",
+ "license": "Apache-2",
+ "dependencies": {
+ "async": "^2.6.3",
+ "debug": "~4.3.1",
+ "eventemitter2": "^6.3.1",
+ "extrareqp2": "^1.0.0",
+ "ws": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/@pm2/js-api/node_modules/async": {
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
+ "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
+ "license": "MIT",
+ "dependencies": {
+ "lodash": "^4.17.14"
+ }
+ },
+ "node_modules/@pm2/js-api/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@pm2/js-api/node_modules/eventemitter2": {
+ "version": "6.4.9",
+ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz",
+ "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==",
+ "license": "MIT"
+ },
+ "node_modules/@pm2/js-api/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/@pm2/pm2-version-check": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@pm2/pm2-version-check/-/pm2-version-check-1.0.4.tgz",
+ "integrity": "sha512-SXsM27SGH3yTWKc2fKR4SYNxsmnvuBQ9dd6QHtEWmiZ/VqaOYPAIlS8+vMcn27YLtAEBGvNRSh3TPNvtjZgfqA==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.1"
+ }
+ },
+ "node_modules/@pm2/pm2-version-check/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
"optional": true
}
}
},
- "node_modules/@swagger-api/apidom-parser-adapter-yaml-1-2/node_modules/tree-sitter": {
- "version": "0.22.1",
- "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.22.1.tgz",
- "integrity": "sha512-gRO+jk2ljxZlIn20QRskIvpLCMtzuLl5T0BY6L9uvPYD17uUrxlxWkvYCiVqED2q2q7CVtY52Uex4WcYo2FEXw==",
- "hasInstallScript": true,
- "optional": true,
+ "node_modules/@pm2/pm2-version-check/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/@redis/bloom": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-5.1.0.tgz",
+ "integrity": "sha512-Gp5RWvVKbvItMU2sd848yhY/BnigToz8H4PYcvlBBSP5cQ3lVP1LMh5Kx2CYBNzCdDabVicwBKNvaoLBqPNqIg==",
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "@redis/client": "^5.1.0"
+ }
+ },
+ "node_modules/@redis/client": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@redis/client/-/client-5.1.0.tgz",
+ "integrity": "sha512-FMD35y2KgCWTBLOfF0MhwDSaIVcu5mOUuTV9Kw3JOWHMgON3+ulht31cjTB/gph0BfD1vzUvCeROeRaf/d+35w==",
+ "dependencies": {
+ "cluster-key-slot": "1.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@redis/json": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@redis/json/-/json-5.1.0.tgz",
+ "integrity": "sha512-laXZt1Rlimk3py5ZoABBnd4xn/8dWbLUWGvVS7avgMhdczS+eWtXpElilJbFpc+7ZpVlol4vaSGFuR8ThDcTFw==",
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "@redis/client": "^5.1.0"
+ }
+ },
+ "node_modules/@redis/search": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@redis/search/-/search-5.1.0.tgz",
+ "integrity": "sha512-afQYMeIdWGNPjr84GxxgJVkolxMW3BBrlNOwhRHPdzbdGh0rTUPjOJpGHBig34ostHX6AhZ6QwqceU1zLluDEg==",
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "@redis/client": "^5.1.0"
+ }
+ },
+ "node_modules/@redis/time-series": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-5.1.0.tgz",
+ "integrity": "sha512-BjKndLXREPeb4ZtxrI6z1bz2FbzBj7LnWyyevNk6Wd7VRWQ3W10LSvJAJwguPD62mSqpTPhy0lMPqFJwo0gS7A==",
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "@redis/client": "^5.1.0"
+ }
+ },
+ "node_modules/@scarf/scarf": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz",
+ "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.8",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
+ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "node_modules/@smithy/abort-controller": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.2.tgz",
+ "integrity": "sha512-Sl/78VDtgqKxN2+1qduaVE140XF+Xg+TafkncspwM4jFP/LHr76ZHmIY/y3V1M0mMLNk+Je6IGbzxy23RSToMw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/chunked-blob-reader": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.0.0.tgz",
+ "integrity": "sha512-+sKqDBQqb036hh4NPaUiEkYFkTUGYzRsn3EuFhyfQfMy6oGHEUJDurLP9Ufb5dasr/XiAmPNMr6wa9afjQB+Gw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/chunked-blob-reader-native": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.0.0.tgz",
+ "integrity": "sha512-R9wM2yPmfEMsUmlMlIgSzOyICs0x9uu7UTHoccMyt7BWw8shcGM8HqB355+BZCPBcySvbTYMs62EgEQkNxz2ig==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-base64": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/config-resolver": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.2.tgz",
+ "integrity": "sha512-7r6mZGwb5LmLJ+zPtkLoznf2EtwEuSWdtid10pjGl/7HefCE4mueOkrfki8JCUm99W6UfP47/r3tbxx9CfBN5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-config-provider": "^4.0.0",
+ "@smithy/util-middleware": "^4.0.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/core": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.3.2.tgz",
+ "integrity": "sha512-GlLv+syoWolhtjX12XplL9BXBu10cjjD8iQC69fiKTrVNOB3Fjt8CVI9ccm6G3bLbMNe1gzrLD7yyMkYo4hchw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/middleware-serde": "^4.0.4",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-body-length-browser": "^4.0.0",
+ "@smithy/util-middleware": "^4.0.2",
+ "@smithy/util-stream": "^4.2.0",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/credential-provider-imds": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.4.tgz",
+ "integrity": "sha512-jN6M6zaGVyB8FmNGG+xOPQB4N89M1x97MMdMnm1ESjljLS3Qju/IegQizKujaNcy2vXAvrz0en8bobe6E55FEA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/types": "^4.2.0",
+ "@smithy/url-parser": "^4.0.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-codec": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.2.tgz",
+ "integrity": "sha512-p+f2kLSK7ZrXVfskU/f5dzksKTewZk8pJLPvER3aFHPt76C2MxD9vNatSfLzzQSQB4FNO96RK4PSXfhD1TTeMQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/crc32": "5.2.0",
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-hex-encoding": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-browser": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.2.tgz",
+ "integrity": "sha512-CepZCDs2xgVUtH7ZZ7oDdZFH8e6Y2zOv8iiX6RhndH69nlojCALSKK+OXwZUgOtUZEUaZ5e1hULVCHYbCn7pug==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/eventstream-serde-universal": "^4.0.2",
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-config-resolver": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.1.0.tgz",
+ "integrity": "sha512-1PI+WPZ5TWXrfj3CIoKyUycYynYJgZjuQo8U+sphneOtjsgrttYybdqESFReQrdWJ+LKt6NEdbYzmmfDBmjX2A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-node": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.2.tgz",
+ "integrity": "sha512-C5bJ/C6x9ENPMx2cFOirspnF9ZsBVnBMtP6BdPl/qYSuUawdGQ34Lq0dMcf42QTjUZgWGbUIZnz6+zLxJlb9aw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/eventstream-serde-universal": "^4.0.2",
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-universal": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.2.tgz",
+ "integrity": "sha512-St8h9JqzvnbB52FtckiHPN4U/cnXcarMniXRXTKn0r4b4XesZOGiAyUdj1aXbqqn1icSqBlzzUsCl6nPB018ng==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/eventstream-codec": "^4.0.2",
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/fetch-http-handler": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.2.tgz",
+ "integrity": "sha512-+9Dz8sakS9pe7f2cBocpJXdeVjMopUDLgZs1yWeu7h++WqSbjUYv/JAJwKwXw1HV6gq1jyWjxuyn24E2GhoEcQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/querystring-builder": "^4.0.2",
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-base64": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-blob-browser": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.2.tgz",
+ "integrity": "sha512-3g188Z3DyhtzfBRxpZjU8R9PpOQuYsbNnyStc/ZVS+9nVX1f6XeNOa9IrAh35HwwIZg+XWk8bFVtNINVscBP+g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/chunked-blob-reader": "^5.0.0",
+ "@smithy/chunked-blob-reader-native": "^4.0.0",
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-node": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.2.tgz",
+ "integrity": "sha512-VnTpYPnRUE7yVhWozFdlxcYknv9UN7CeOqSrMH+V877v4oqtVYuoqhIhtSjmGPvYrYnAkaM61sLMKHvxL138yg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-buffer-from": "^4.0.0",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-stream-node": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.2.tgz",
+ "integrity": "sha512-POWDuTznzbIwlEXEvvXoPMS10y0WKXK790soe57tFRfvf4zBHyzE529HpZMqmDdwG9MfFflnyzndUQ8j78ZdSg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/invalid-dependency": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.2.tgz",
+ "integrity": "sha512-GatB4+2DTpgWPday+mnUkoumP54u/MDM/5u44KF9hIu8jF0uafZtQLcdfIKkIcUNuF/fBojpLEHZS/56JqPeXQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/is-array-buffer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz",
+ "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/md5-js": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.2.tgz",
+ "integrity": "sha512-Hc0R8EiuVunUewCse2syVgA2AfSRco3LyAv07B/zCOMa+jpXI9ll+Q21Nc6FAlYPcpNcAXqBzMhNs1CD/pP2bA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-content-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.2.tgz",
+ "integrity": "sha512-hAfEXm1zU+ELvucxqQ7I8SszwQ4znWMbNv6PLMndN83JJN41EPuS93AIyh2N+gJ6x8QFhzSO6b7q2e6oClDI8A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-endpoint": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.5.tgz",
+ "integrity": "sha512-WlpC9KVkajQf7RaGwi3n6lhHZzYTgm2PyX/2JjcwSHG417gFloNmYqN8rzDRXjT527/ZxZuvCsqq1gWZPW8lag==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.3.2",
+ "@smithy/middleware-serde": "^4.0.4",
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/shared-ini-file-loader": "^4.0.2",
+ "@smithy/types": "^4.2.0",
+ "@smithy/url-parser": "^4.0.2",
+ "@smithy/util-middleware": "^4.0.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-retry": {
+ "version": "4.1.6",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.6.tgz",
+ "integrity": "sha512-bl8q95nvCf7d22spxsBfs2giUDFf7prWLAxF5tmfgGBYHbUNW+OfnwMnabC15GMLA2AoE4HOtQR18a59lx6Blw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/service-error-classification": "^4.0.3",
+ "@smithy/smithy-client": "^4.2.5",
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-middleware": "^4.0.2",
+ "@smithy/util-retry": "^4.0.3",
+ "tslib": "^2.6.2",
+ "uuid": "^9.0.1"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-serde": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.4.tgz",
+ "integrity": "sha512-CaLvBtz+Xgs7eOwoinTXhZ02/9u8b28RT8lQAaDh7Q59nygeYYp1UiJjwl6zsay+lp0qVT/S7qLVI5RgcxjyfQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-stack": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.2.tgz",
+ "integrity": "sha512-eSPVcuJJGVYrFYu2hEq8g8WWdJav3sdrI4o2c6z/rjnYDd3xH9j9E7deZQCzFn4QvGPouLngH3dQ+QVTxv5bOQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/node-config-provider": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.1.1.tgz",
+ "integrity": "sha512-1slS5jf5icHETwl5hxEVBj+mh6B+LbVW4yRINsGtUKH+nxM5Pw2H59+qf+JqYFCHp9jssG4vX81f5WKnjMN3Vw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/shared-ini-file-loader": "^4.0.2",
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/node-http-handler": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.4.tgz",
+ "integrity": "sha512-/mdqabuAT3o/ihBGjL94PUbTSPSRJ0eeVTdgADzow0wRJ0rN4A27EOrtlK56MYiO1fDvlO3jVTCxQtQmK9dZ1g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/abort-controller": "^4.0.2",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/querystring-builder": "^4.0.2",
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/property-provider": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.2.tgz",
+ "integrity": "sha512-wNRoQC1uISOuNc2s4hkOYwYllmiyrvVXWMtq+TysNRVQaHm4yoafYQyjN/goYZS+QbYlPIbb/QRjaUZMuzwQ7A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/protocol-http": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.0.tgz",
+ "integrity": "sha512-KxAOL1nUNw2JTYrtviRRjEnykIDhxc84qMBzxvu1MUfQfHTuBlCG7PA6EdVwqpJjH7glw7FqQoFxUJSyBQgu7g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/querystring-builder": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.2.tgz",
+ "integrity": "sha512-NTOs0FwHw1vimmQM4ebh+wFQvOwkEf/kQL6bSM1Lock+Bv4I89B3hGYoUEPkmvYPkDKyp5UdXJYu+PoTQ3T31Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-uri-escape": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/querystring-parser": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.2.tgz",
+ "integrity": "sha512-v6w8wnmZcVXjfVLjxw8qF7OwESD9wnpjp0Dqry/Pod0/5vcEA3qxCr+BhbOHlxS8O+29eLpT3aagxXGwIoEk7Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/service-error-classification": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.3.tgz",
+ "integrity": "sha512-FTbcajmltovWMjj3tksDQdD23b2w6gH+A0DYA1Yz3iSpjDj8fmkwy62UnXcWMy4d5YoMoSyLFHMfkEVEzbiN8Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.2.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/shared-ini-file-loader": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.2.tgz",
+ "integrity": "sha512-J9/gTWBGVuFZ01oVA6vdb4DAjf1XbDhK6sLsu3OS9qmLrS6KB5ygpeHiM3miIbj1qgSJ96GYszXFWv6ErJ8QEw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/signature-v4": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.1.0.tgz",
+ "integrity": "sha512-4t5WX60sL3zGJF/CtZsUQTs3UrZEDO2P7pEaElrekbLqkWPYkgqNW1oeiNYC6xXifBnT9dVBOnNQRvOE9riU9w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^4.0.0",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-hex-encoding": "^4.0.0",
+ "@smithy/util-middleware": "^4.0.2",
+ "@smithy/util-uri-escape": "^4.0.0",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/smithy-client": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.2.5.tgz",
+ "integrity": "sha512-T3gA/TShe52Ln0ywWGVoDiqRvaxqvrU0CKRRmzT71/I1rRBD8mY85rvMMME6vw5RpBLJC9ADmXSLmpohF7RRhA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.3.2",
+ "@smithy/middleware-endpoint": "^4.1.5",
+ "@smithy/middleware-stack": "^4.0.2",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-stream": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/types": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.2.0.tgz",
+ "integrity": "sha512-7eMk09zQKCO+E/ivsjQv+fDlOupcFUCSC/L2YUPgwhvowVGWbPQHjEFcmjt7QQ4ra5lyowS92SV53Zc6XD4+fg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/url-parser": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.2.tgz",
+ "integrity": "sha512-Bm8n3j2ScqnT+kJaClSVCMeiSenK6jVAzZCNewsYWuZtnBehEz4r2qP0riZySZVfzB+03XZHJeqfmJDkeeSLiQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/querystring-parser": "^4.0.2",
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-base64": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz",
+ "integrity": "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^4.0.0",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-body-length-browser": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz",
+ "integrity": "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-body-length-node": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz",
+ "integrity": "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-buffer-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz",
+ "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-config-provider": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz",
+ "integrity": "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-defaults-mode-browser": {
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.13.tgz",
+ "integrity": "sha512-HCLfXAyTEpVWLuyxDABg8UQukeRwChL1UErpSQ4KJK2ZoadmXuQY68pTL9KcuEtasTkIjnzyLUL9vhLdJ3VFHQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/smithy-client": "^4.2.5",
+ "@smithy/types": "^4.2.0",
+ "bowser": "^2.11.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-defaults-mode-node": {
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.13.tgz",
+ "integrity": "sha512-lu8E2RyzKzzFbNu4ICmY/2HltMZlJxMNg3saJ+r8I9vWbWbwdX7GOWUJdP4fbjEOm6aa52mnnd+uIRrT3dNEyA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/config-resolver": "^4.1.2",
+ "@smithy/credential-provider-imds": "^4.0.4",
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/smithy-client": "^4.2.5",
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-endpoints": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.4.tgz",
+ "integrity": "sha512-VfFATC1bmZLV2858B/O1NpMcL32wYo8DPPhHxYxDCodDl3f3mSZ5oJheW1IF91A0EeAADz2WsakM/hGGPGNKLg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.1.1",
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-hex-encoding": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz",
+ "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-middleware": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.2.tgz",
+ "integrity": "sha512-6GDamTGLuBQVAEuQ4yDQ+ti/YINf/MEmIegrEeg7DdB/sld8BX1lqt9RRuIcABOhAGTA50bRbPzErez7SlDtDQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-retry": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.3.tgz",
+ "integrity": "sha512-DPuYjZQDXmKr/sNvy9Spu8R/ESa2e22wXZzSAY6NkjOLj6spbIje/Aq8rT97iUMdDj0qHMRIe+bTxvlU74d9Ng==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/service-error-classification": "^4.0.3",
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-stream": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.0.tgz",
+ "integrity": "sha512-Vj1TtwWnuWqdgQI6YTUF5hQ/0jmFiOYsc51CSMgj7QfyO+RF4EnT2HNjoviNlOOmgzgvf3f5yno+EiC4vrnaWQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/fetch-http-handler": "^5.0.2",
+ "@smithy/node-http-handler": "^4.0.4",
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-base64": "^4.0.0",
+ "@smithy/util-buffer-from": "^4.0.0",
+ "@smithy/util-hex-encoding": "^4.0.0",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-uri-escape": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz",
+ "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-utf8": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz",
+ "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-waiter": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.3.tgz",
+ "integrity": "sha512-JtaY3FxmD+te+KSI2FJuEcfNC9T/DGGVf551babM7fAaXhjJUt7oSYurH1Devxd2+BOSUACCgt3buinx4UnmEA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/abort-controller": "^4.0.2",
+ "@smithy/types": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@streamparser/json": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@streamparser/json/-/json-0.0.6.tgz",
+ "integrity": "sha512-vL9EVn/v+OhZ+Wcs6O4iKE9EUpwHUqHmCtNUMWjqp+6dr85+XPOSGTEsqYNq1Vn04uk9SWlOVmx9J48ggJVT2Q=="
+ },
+ "node_modules/@swagger-api/apidom-ast": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ast/-/apidom-ast-1.0.0-beta.39.tgz",
+ "integrity": "sha512-EWeSOtvI8XpbYMRkDyu4qAIlivhcplrskpau2cbrWfXGBjrqEtmHqWlbJ9xoXJbNshbIcZ0Z77QdxicimGjs0w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-error": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "unraw": "^3.0.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-core": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-core/-/apidom-core-1.0.0-beta.39.tgz",
+ "integrity": "sha512-tYZSVA+uDFvBJmnP104d8Qb/mye8B6ykNviohHAngHsy8ElcOPzSi5GKwwmJgf3taWzipMqWNM0ch5KytbXTqw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-ast": "^1.0.0-beta.39",
+ "@swagger-api/apidom-error": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "minim": "~0.23.8",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "short-unique-id": "^5.3.2",
+ "ts-mixer": "^6.0.3"
+ }
+ },
+ "node_modules/@swagger-api/apidom-error": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-error/-/apidom-error-1.0.0-beta.39.tgz",
+ "integrity": "sha512-vQ3xQaRQGP9kNNBEDcFCmUd2PT9rCtYdkCyqYWZMxHBm5dXSBC/dQaC5VN1DbqQygE16fSQC+c5sqOrwg5d5WQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.20.7"
+ }
+ },
+ "node_modules/@swagger-api/apidom-json-pointer": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-json-pointer/-/apidom-json-pointer-1.0.0-beta.39.tgz",
+ "integrity": "sha512-gPDNT+MCs/B1XYuNpmnz0rOHQ0ssN9YjVDqeGkX61v03BLJUF/JZKMo3J3FA2mgKb6ap+kRHzpzw5PpHLwRKAw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-error": "^1.0.0-beta.39",
+ "@swaggerexpert/json-pointer": "^2.10.1"
+ }
+ },
+ "node_modules/@swagger-api/apidom-ns-api-design-systems": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-api-design-systems/-/apidom-ns-api-design-systems-1.0.0-beta.39.tgz",
+ "integrity": "sha512-MpdCb8KS3Tz1mGTrU0XC0Q2OcsrUWKB+buFPzLFOv0dU36ArARERX+Mz6aCJQ1CqnkFVM49uMe2NECO93ZR52w==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-error": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-openapi-3-1": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "ts-mixer": "^6.0.3"
+ }
+ },
+ "node_modules/@swagger-api/apidom-ns-arazzo-1": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-arazzo-1/-/apidom-ns-arazzo-1-1.0.0-beta.39.tgz",
+ "integrity": "sha512-gIiZhlt51JxEZBAZ5PfHV1c73SMQJiwJX5DnazGehMO+ojR4HyLPFh1lc6mChMxPyPlRFOfqnmx/hmNcJ/XRiA==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-json-schema-2020-12": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "ts-mixer": "^6.0.3"
+ }
+ },
+ "node_modules/@swagger-api/apidom-ns-asyncapi-2": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-asyncapi-2/-/apidom-ns-asyncapi-2-1.0.0-beta.39.tgz",
+ "integrity": "sha512-Jtdo+6MgVhf8HynjRo5pIj+aYYICAQGwRkd0n0YtOhvvKoI0gWEMpcRkDbJrNcNYOHaSxMlQfotGlTCaMl7QJQ==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-json-schema-draft-7": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "ts-mixer": "^6.0.3"
+ }
+ },
+ "node_modules/@swagger-api/apidom-ns-json-schema-2019-09": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-2019-09/-/apidom-ns-json-schema-2019-09-1.0.0-beta.39.tgz",
+ "integrity": "sha512-I/XP4zbrWAmnq2KWPtbb9DKLWgzYFovIiSQOyh47bJqbYgz64/IhoZb/uGihZojVVHSqeeJH9o6JOahqHQzKOw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-error": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-json-schema-draft-7": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "ts-mixer": "^6.0.4"
+ }
+ },
+ "node_modules/@swagger-api/apidom-ns-json-schema-2020-12": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-2020-12/-/apidom-ns-json-schema-2020-12-1.0.0-beta.39.tgz",
+ "integrity": "sha512-9bpMp96fb76lOqeggtyCU457K/XBLyw3O9fxdVS3Tevhf8P3SJ6QpabmweRb6kFt4vI3+DiBschJGn0iqmlcXw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-error": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-json-schema-2019-09": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "ts-mixer": "^6.0.4"
+ }
+ },
+ "node_modules/@swagger-api/apidom-ns-json-schema-draft-4": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-4/-/apidom-ns-json-schema-draft-4-1.0.0-beta.39.tgz",
+ "integrity": "sha512-F25tm/nwPl1rRnUHzaVw4SAeASodO60oAtWX+GF3K61WEx/Aao4Maldv3CQtAoUk8L0Ml0l1KZL00sgfikwqlw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-ast": "^1.0.0-beta.39",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "ts-mixer": "^6.0.4"
+ }
+ },
+ "node_modules/@swagger-api/apidom-ns-json-schema-draft-6": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-6/-/apidom-ns-json-schema-draft-6-1.0.0-beta.39.tgz",
+ "integrity": "sha512-E2fQQHWIRtbM5C1m1EL95MQNDPL98mlgYomPQDDUEFbYrH3u9BQGAgpIu4KuYasKquyuhx9YXqS/jLRhMCRfAQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-error": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-json-schema-draft-4": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "ts-mixer": "^6.0.4"
+ }
+ },
+ "node_modules/@swagger-api/apidom-ns-json-schema-draft-7": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-7/-/apidom-ns-json-schema-draft-7-1.0.0-beta.39.tgz",
+ "integrity": "sha512-mhzb7n3pm0yfYuM9bZowYMp6L61Cz+HrbjBowUIt5iOMMAATQd6x209pj81hnSmgHmEJCgv+8IO9dvweme698A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-error": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-json-schema-draft-6": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "ts-mixer": "^6.0.4"
+ }
+ },
+ "node_modules/@swagger-api/apidom-ns-openapi-2": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-2/-/apidom-ns-openapi-2-1.0.0-beta.39.tgz",
+ "integrity": "sha512-/Cjggp0eAM1GfKeLu53sLjCV9lFVUMucFruXJnD1TWdCKv5S5JAKsGBASbchw8hvwrfx6sPHslzZFV+tZKbn2Q==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-error": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-json-schema-draft-4": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "ts-mixer": "^6.0.3"
+ }
+ },
+ "node_modules/@swagger-api/apidom-ns-openapi-3-0": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-0/-/apidom-ns-openapi-3-0-1.0.0-beta.39.tgz",
+ "integrity": "sha512-lvNlUtCmyHH8+52qOhgXXdzy4HEYA+t7xnFNvDb6dtP+epXCexux3uRs8+xEYBHo/WqUGzjdwd0qKFRgyP7Lrw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-error": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-json-schema-draft-4": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "ts-mixer": "^6.0.3"
+ }
+ },
+ "node_modules/@swagger-api/apidom-ns-openapi-3-1": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-1/-/apidom-ns-openapi-3-1-1.0.0-beta.39.tgz",
+ "integrity": "sha512-sXMJxTGL2F36Uyv9iqvPwvzsD5NJM/dJ52tUuiJP8h4RqXwjrOC86hqf1/Xk/rxgpZShhW4PNEqifvPq/Mto3w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-ast": "^1.0.0-beta.39",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-json-pointer": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-json-schema-2020-12": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-openapi-3-0": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "ts-mixer": "^6.0.3"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-json": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-json/-/apidom-parser-adapter-api-design-systems-json-1.0.0-beta.39.tgz",
+ "integrity": "sha512-jrPxZMvE6I2X8FUx4ri7VTMy2wTNOLLz+qXSx9sSXWULImqwdscvEwSVug8zdBQYMy8HXwt0wHpxlGLXBEmL8Q==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-api-design-systems": "^1.0.0-beta.39",
+ "@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-yaml": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/-/apidom-parser-adapter-api-design-systems-yaml-1.0.0-beta.39.tgz",
+ "integrity": "sha512-JKyRYc4cBajPkIpO0YTJnxI+p8ubXfA+/1L8Fpq5kDPAI5Wh744iZ/scVHTgpgY8g+GbPqIoWB0ilQbEdlF5Sg==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-api-design-systems": "^1.0.0-beta.39",
+ "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-arazzo-json-1": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-arazzo-json-1/-/apidom-parser-adapter-arazzo-json-1-1.0.0-beta.39.tgz",
+ "integrity": "sha512-qlQuj4jsEPpLRH4wpkMjbR3Id3qb4n/oerv4cKCi1TYJJphC7DG7QRS90tYjaAF7n2YA8HxUcEIu2+Y5QZKyMw==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-arazzo-1": "^1.0.0-beta.39",
+ "@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-arazzo-yaml-1": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-arazzo-yaml-1/-/apidom-parser-adapter-arazzo-yaml-1-1.0.0-beta.39.tgz",
+ "integrity": "sha512-MUChnj6dJZRGDtIIVItIojzDNBEdan8KkuV+3U1l8bBA4eJQIq7yzHYk7fq6bl4Yd17HG0HT+1xckbUnj5Ay4A==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-arazzo-1": "^1.0.0-beta.39",
+ "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-json-2": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-json-2/-/apidom-parser-adapter-asyncapi-json-2-1.0.0-beta.39.tgz",
+ "integrity": "sha512-G+xIeYGetnCM3ylsWSwSyqCntpT6gt2Bv3f6hu/IonZxxCy2HqUl9JS41XF/cJHCoBchJU3G+bjOZXN22W3Xzw==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-asyncapi-2": "^1.0.0-beta.39",
+ "@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/-/apidom-parser-adapter-asyncapi-yaml-2-1.0.0-beta.39.tgz",
+ "integrity": "sha512-VPwlMRwtMQtPmEv6JXNefBBjAK/IxPsq9XWP/7kJZQ6CDp6ljHrMJDPAHZNundSL09xu7Wbz6KVGcpruUPiWmA==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-asyncapi-2": "^1.0.0-beta.39",
+ "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-json": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-json/-/apidom-parser-adapter-json-1.0.0-beta.39.tgz",
+ "integrity": "sha512-Rg2SgI06CDTdm3qs3A5pNvhonVxa2jOcwypxyhKngelIHaTuOPgaFA6qyCIvX0oIhwTcKcvV+5tPlGIR3vshpA==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-ast": "^1.0.0-beta.39",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-error": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "tree-sitter": "=0.22.1",
+ "tree-sitter-json": "=0.24.8",
+ "web-tree-sitter": "=0.24.5"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-json/node_modules/tree-sitter": {
+ "version": "0.22.1",
+ "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.22.1.tgz",
+ "integrity": "sha512-gRO+jk2ljxZlIn20QRskIvpLCMtzuLl5T0BY6L9uvPYD17uUrxlxWkvYCiVqED2q2q7CVtY52Uex4WcYo2FEXw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "node-addon-api": "^8.2.1",
+ "node-gyp-build": "^4.8.2"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-2": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-2/-/apidom-parser-adapter-openapi-json-2-1.0.0-beta.39.tgz",
+ "integrity": "sha512-DYB3jGcSnTu1ykbAKkMo550QW0BjnHlGxi1NaBbVYzdMfPYbBSQnDB3zYAwgakpoQx89OztFSlrNQ+3P8wuuSw==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-openapi-2": "^1.0.0-beta.39",
+ "@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-0": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-0/-/apidom-parser-adapter-openapi-json-3-0-1.0.0-beta.39.tgz",
+ "integrity": "sha512-4ueWFNc3N4YZb7fTwsgrhWzdCo3TnZ7HgK5fPW3m0+Hm2wko2WYIUCIxU33Ef4DB+0Hd8y4Abjv8Mz0CCxRaeg==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-openapi-3-0": "^1.0.0-beta.39",
+ "@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-1": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-1/-/apidom-parser-adapter-openapi-json-3-1-1.0.0-beta.39.tgz",
+ "integrity": "sha512-8K/9J1CnQAwVqN+pvP9PH607WKA7WimNmZiyczgfnOgq93PUozNavrK97lwUUOQcZUmQra8pG2XrOrZZwd/M5w==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-openapi-3-1": "^1.0.0-beta.39",
+ "@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-2": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-2/-/apidom-parser-adapter-openapi-yaml-2-1.0.0-beta.39.tgz",
+ "integrity": "sha512-EfzVZrYTnwNGXUXIOrZkigQxdze+VdXxJWp55t3CWTy0CA7w9eM+PDpzHu7iqJgXqTOixMGy02Gzyv6N6sDj8A==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-openapi-2": "^1.0.0-beta.39",
+ "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/-/apidom-parser-adapter-openapi-yaml-3-0-1.0.0-beta.39.tgz",
+ "integrity": "sha512-ElHueuGdwB35VeZaJnmhZE3ILGE8F74ThJqgTbY+F2JcNo4O8cBkoCq9syw1pJ+l2JoAUErmxaTOR+zNA/wK+g==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-openapi-3-0": "^1.0.0-beta.39",
+ "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/-/apidom-parser-adapter-openapi-yaml-3-1-1.0.0-beta.39.tgz",
+ "integrity": "sha512-lNSXp+vGcsA/d/3ukXJeovAnO5oxcTJ5OvFBL84grJvK1C6E2v0AOfsMlUEipIRNhIHq3zYKpUnhFJyE13VqXA==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-ns-openapi-3-1": "^1.0.0-beta.39",
+ "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-yaml-1-2": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-yaml-1-2/-/apidom-parser-adapter-yaml-1-2-1.0.0-beta.39.tgz",
+ "integrity": "sha512-30Lhgkg2ZrHY7tQ5h9umjWWhy0Fqcoi28SXJ9vtdj1cLSnFvclaLe5ZGbXP3wdW4sXZO0As3+msL9tMwrUJ/7w==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-ast": "^1.0.0-beta.39",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-error": "^1.0.0-beta.39",
+ "@tree-sitter-grammars/tree-sitter-yaml": "=0.7.0",
+ "@types/ramda": "~0.30.0",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0",
+ "tree-sitter": "=0.22.1",
+ "web-tree-sitter": "=0.24.5"
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-yaml-1-2/node_modules/@tree-sitter-grammars/tree-sitter-yaml": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@tree-sitter-grammars/tree-sitter-yaml/-/tree-sitter-yaml-0.7.0.tgz",
+ "integrity": "sha512-GOMIK3IaDvECD0eZEhAsLl03RMtM1E8StxuGMn6PpMKFg7jyQ+jSzxJZ4Jmc/tYitah9/AECt8o4tlRQ5yEZQg==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "node-addon-api": "^8.3.0",
+ "node-gyp-build": "^4.8.4"
+ },
+ "peerDependencies": {
+ "tree-sitter": "^0.22.1"
+ },
+ "peerDependenciesMeta": {
+ "tree-sitter": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@swagger-api/apidom-parser-adapter-yaml-1-2/node_modules/tree-sitter": {
+ "version": "0.22.1",
+ "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.22.1.tgz",
+ "integrity": "sha512-gRO+jk2ljxZlIn20QRskIvpLCMtzuLl5T0BY6L9uvPYD17uUrxlxWkvYCiVqED2q2q7CVtY52Uex4WcYo2FEXw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "node-addon-api": "^8.2.1",
+ "node-gyp-build": "^4.8.2"
+ }
+ },
+ "node_modules/@swagger-api/apidom-reference": {
+ "version": "1.0.0-beta.39",
+ "resolved": "https://registry.npmjs.org/@swagger-api/apidom-reference/-/apidom-reference-1.0.0-beta.39.tgz",
+ "integrity": "sha512-PrV2/3Z6XGJPj4fv1JazY1dKjlnAg/BN22UQdUOzA5/A0TkfbImt8uVQuVzQSL2P8RA6G9TDsdpOalj80N47rw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@babel/runtime-corejs3": "^7.26.10",
+ "@swagger-api/apidom-core": "^1.0.0-beta.39",
+ "@swagger-api/apidom-error": "^1.0.0-beta.39",
+ "@types/ramda": "~0.30.0",
+ "axios": "^1.9.0",
+ "minimatch": "^7.4.3",
+ "process": "^0.11.10",
+ "ramda": "~0.30.0",
+ "ramda-adjunct": "^5.0.0"
+ },
+ "optionalDependencies": {
+ "@swagger-api/apidom-json-pointer": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-ns-arazzo-1": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-ns-asyncapi-2": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-ns-openapi-2": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-ns-openapi-3-0": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-ns-openapi-3-1": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-parser-adapter-api-design-systems-json": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-parser-adapter-arazzo-json-1": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-parser-adapter-arazzo-yaml-1": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-parser-adapter-asyncapi-json-2": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-parser-adapter-openapi-json-2": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-parser-adapter-openapi-json-3-0": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-parser-adapter-openapi-json-3-1": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-parser-adapter-openapi-yaml-2": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": "^1.0.0-beta.3 <1.0.0-rc.0",
+ "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-beta.3 <1.0.0-rc.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-reference/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@swagger-api/apidom-reference/node_modules/minimatch": {
+ "version": "7.4.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz",
+ "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@swaggerexpert/cookie": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@swaggerexpert/cookie/-/cookie-2.0.2.tgz",
+ "integrity": "sha512-DPI8YJ0Vznk4CT+ekn3rcFNq1uQwvUHZhH6WvTSPD0YKBIlMS9ur2RYKghXuxxOiqOam/i4lHJH4xTIiTgs3Mg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "apg-lite": "^1.0.3"
+ },
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/@swaggerexpert/json-pointer": {
+ "version": "2.10.2",
+ "resolved": "https://registry.npmjs.org/@swaggerexpert/json-pointer/-/json-pointer-2.10.2.tgz",
+ "integrity": "sha512-qMx1nOrzoB+PF+pzb26Q4Tc2sOlrx9Ba2UBNX9hB31Omrq+QoZ2Gly0KLrQWw4Of1AQ4J9lnD+XOdwOdcdXqqw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "apg-lite": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/@tootallnate/quickjs-emscripten": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
+ "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz",
+ "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
+ "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/hast": {
+ "version": "2.3.10",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz",
+ "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2"
+ }
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "22.15.17",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz",
+ "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@types/ramda": {
+ "version": "0.30.2",
+ "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.30.2.tgz",
+ "integrity": "sha512-PyzHvjCalm2BRYjAU6nIB3TprYwMNOUY/7P/N8bSzp9W/yM2YrtGtAnnVtaCNSeOZ8DzKyFDvaqQs7LnWwwmBA==",
+ "license": "MIT",
+ "dependencies": {
+ "types-ramda": "^0.30.1"
+ }
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/@types/unist": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
+ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
+ "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/uuid": {
+ "version": "9.0.8",
+ "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
+ "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.14.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
+ "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
+ "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/amp": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/amp/-/amp-0.3.1.tgz",
+ "integrity": "sha512-OwIuC4yZaRogHKiuU5WlMR5Xk/jAcpPtawWL05Gj8Lvm2F6mwoJt4O/bHI+DHwG79vWd+8OFYM4/BzYqyRd3qw==",
+ "license": "MIT"
+ },
+ "node_modules/amp-message": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/amp-message/-/amp-message-0.1.2.tgz",
+ "integrity": "sha512-JqutcFwoU1+jhv7ArgW38bqrE+LQdcRv4NxNw0mp0JHQyB6tXesWRjtYKlDgHRY2o3JE5UTaBGUK8kSWUdxWUg==",
+ "license": "MIT",
+ "dependencies": {
+ "amp": "0.3.1"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/apg-lite": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/apg-lite/-/apg-lite-1.0.4.tgz",
+ "integrity": "sha512-B32zCN3IdHIc99Vy7V9BaYTUzLeRA8YXYY1aQD1/5I2aqIrO0coi4t6hJPqMisidlBxhyME8UexkHt31SlR6Og==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/append-field": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
+ "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
+ "license": "MIT"
+ },
+ "node_modules/archiver": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz",
+ "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==",
+ "license": "MIT",
+ "dependencies": {
+ "archiver-utils": "^2.1.0",
+ "async": "^3.2.4",
+ "buffer-crc32": "^0.2.1",
+ "readable-stream": "^3.6.0",
+ "readdir-glob": "^1.1.2",
+ "tar-stream": "^2.2.0",
+ "zip-stream": "^4.1.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/archiver-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz",
+ "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
+ "license": "MIT",
+ "dependencies": {
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.2.0",
+ "lazystream": "^1.0.0",
+ "lodash.defaults": "^4.2.0",
+ "lodash.difference": "^4.5.0",
+ "lodash.flatten": "^4.4.0",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.union": "^4.6.0",
+ "normalize-path": "^3.0.0",
+ "readable-stream": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/archiver/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/are-docs-informative": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz",
+ "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "license": "Python-2.0"
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "license": "MIT"
+ },
+ "node_modules/asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+ "license": "MIT"
+ },
+ "node_modules/ast-types": {
+ "version": "0.13.4",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
+ "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/async": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
+ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
+ "license": "MIT"
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/autolinker": {
+ "version": "3.16.2",
+ "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-3.16.2.tgz",
+ "integrity": "sha512-JiYl7j2Z19F9NdTmirENSUUIIL/9MytEWtmzhfmsKPCp9E+G35Y0UNCMoM9tFigxT59qSc8Ml2dlZXOCVTYwuA==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.3.0"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/aws-sdk": {
+ "version": "2.1692.0",
+ "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1692.0.tgz",
+ "integrity": "sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "buffer": "4.9.2",
+ "events": "1.1.1",
+ "ieee754": "1.1.13",
+ "jmespath": "0.16.0",
+ "querystring": "0.2.0",
+ "sax": "1.2.1",
+ "url": "0.10.3",
+ "util": "^0.12.4",
+ "uuid": "8.0.0",
+ "xml2js": "0.6.2"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/aws-sdk/node_modules/uuid": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz",
+ "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==",
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/aws-ssl-profiles": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz",
+ "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/axios": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
+ "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/babel-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/transform": "^29.7.0",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.6.3",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz",
+ "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-import-attributes": "^7.24.7",
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT"
+ },
+ "node_modules/base32.js": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.0.1.tgz",
+ "integrity": "sha512-EGHIRiegFa62/SsA1J+Xs2tIzludPdzM064N9wjbiEgHnGnJ1V0WEpA4pEwCYT5nDvZk3ubf0shqaCS7k6xeUQ==",
+ "license": "MIT"
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/basic-ftp": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
+ "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/bcryptjs": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.2.tgz",
+ "integrity": "sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==",
+ "license": "BSD-3-Clause",
+ "bin": {
+ "bcrypt": "bin/bcrypt"
+ }
+ },
+ "node_modules/big-integer": {
+ "version": "1.6.52",
+ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz",
+ "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==",
+ "license": "Unlicense",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/binary": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz",
+ "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==",
+ "license": "MIT",
+ "dependencies": {
+ "buffers": "~0.1.1",
+ "chainsaw": "~0.1.0"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/bl/node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/bl/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/blessed": {
+ "version": "0.1.81",
+ "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz",
+ "integrity": "sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==",
+ "license": "MIT",
+ "bin": {
+ "blessed": "bin/tput.js"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/bluebird": {
+ "version": "3.4.7",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz",
+ "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==",
+ "license": "MIT"
+ },
+ "node_modules/bodec": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/bodec/-/bodec-0.1.0.tgz",
+ "integrity": "sha512-Ylo+MAo5BDUq1KA3f3R/MFhh+g8cnHmo8bz3YPGhI1znrMaf77ol1sfvYJzsw3nTE+Y2GryfDxBaR+AqpAkEHQ==",
+ "license": "MIT"
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.3",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
+ "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.5",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.13.0",
+ "raw-body": "2.5.2",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/bowser": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
+ "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==",
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.24.5",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz",
+ "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001716",
+ "electron-to-chromium": "^1.5.149",
+ "node-releases": "^2.0.19",
+ "update-browserslist-db": "^1.1.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "4.9.2",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
+ "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4",
+ "isarray": "^1.0.0"
+ }
+ },
+ "node_modules/buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "license": "MIT"
+ },
+ "node_modules/buffer-indexof-polyfill": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz",
+ "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/buffers": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz",
+ "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==",
+ "engines": {
+ "node": ">=0.2.0"
+ }
+ },
+ "node_modules/busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "dependencies": {
+ "streamsearch": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=10.16.0"
+ }
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
+ "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.0",
+ "es-define-property": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/call-me-maybe": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
+ "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==",
+ "license": "MIT"
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001718",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz",
+ "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chainsaw": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz",
+ "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==",
+ "license": "MIT/X11",
+ "dependencies": {
+ "traverse": ">=0.3.0 <0.4"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/character-entities": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
+ "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
+ "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-reference-invalid": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
+ "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/charm": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz",
+ "integrity": "sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==",
+ "license": "MIT/X11"
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz",
+ "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/classnames": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
+ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
+ "license": "MIT"
+ },
+ "node_modules/cli-tableau": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/cli-tableau/-/cli-tableau-2.0.1.tgz",
+ "integrity": "sha512-he+WTicka9cl0Fg/y+YyxcN6/bfQ/1O3QmgxRXDhABKqLzvoOSM4fMzp39uMyLBulAFuywD2N7UaoQE7WaADxQ==",
+ "dependencies": {
+ "chalk": "3.0.0"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/cli-tableau/node_modules/chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cluster-key-slot": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
+ "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
+ "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/comma-separated-tokens": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz",
+ "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/commander": {
+ "version": "2.15.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
+ "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
+ "license": "MIT"
+ },
+ "node_modules/comment-parser": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
+ "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/component-emitter": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
+ "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/compress-commons": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz",
+ "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-crc32": "^0.2.13",
+ "crc32-stream": "^4.0.2",
+ "normalize-path": "^3.0.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/compress-commons/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "license": "MIT"
+ },
+ "node_modules/concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "engines": [
+ "node >= 0.8"
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-parser": {
+ "version": "1.4.7",
+ "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
+ "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "0.7.2",
+ "cookie-signature": "1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
+ "license": "MIT"
+ },
+ "node_modules/cookiejar": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
+ "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
+ "license": "MIT"
+ },
+ "node_modules/copy-to-clipboard": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
+ "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==",
+ "license": "MIT",
+ "dependencies": {
+ "toggle-selection": "^1.0.6"
+ }
+ },
+ "node_modules/core-js-pure": {
+ "version": "3.42.0",
+ "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.42.0.tgz",
+ "integrity": "sha512-007bM04u91fF4kMgwom2I5cQxAFIy8jVulgr9eozILl/SZE53QOqnW/+vviC+wQWLv+AunBG+8Q0TLoeSsSxRQ==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "license": "MIT"
+ },
+ "node_modules/cors": {
+ "version": "2.8.5",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
+ "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+ "license": "MIT",
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/crc-32": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
+ "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
+ "license": "Apache-2.0",
+ "bin": {
+ "crc32": "bin/crc32.njs"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/crc32-stream": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz",
+ "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==",
+ "license": "MIT",
+ "dependencies": {
+ "crc-32": "^1.2.0",
+ "readable-stream": "^3.4.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/crc32-stream/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/create-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
+ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "node-addon-api": "^8.2.1",
- "node-gyp-build": "^4.8.2"
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "prompts": "^2.0.1"
+ },
+ "bin": {
+ "create-jest": "bin/create-jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@swagger-api/apidom-reference": {
- "version": "1.0.0-beta.12",
- "resolved": "https://registry.npmjs.org/@swagger-api/apidom-reference/-/apidom-reference-1.0.0-beta.12.tgz",
- "integrity": "sha512-4A5dvra9NCsl9Dp3x3UyNV3tyTl1LJwvNowaLfMuY5r8jtQLzkcCW+CLPyP2Y64qeT30sklZp7/M3VVd6jKPOg==",
+ "node_modules/croner": {
+ "version": "4.1.97",
+ "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz",
+ "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==",
+ "license": "MIT"
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/runtime-corejs3": "^7.20.7",
- "@swagger-api/apidom-core": "^1.0.0-beta.12",
- "@types/ramda": "~0.30.0",
- "axios": "^1.7.4",
- "minimatch": "^7.4.3",
- "process": "^0.11.10",
- "ramda": "~0.30.0",
- "ramda-adjunct": "^5.0.0"
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
},
- "optionalDependencies": {
- "@swagger-api/apidom-error": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-json-pointer": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-ns-asyncapi-2": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-ns-openapi-2": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-ns-openapi-3-0": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-ns-openapi-3-1": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-ns-workflows-1": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-parser-adapter-api-design-systems-json": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-parser-adapter-asyncapi-json-2": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-parser-adapter-openapi-json-2": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-parser-adapter-openapi-json-3-0": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-parser-adapter-openapi-json-3-1": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-parser-adapter-openapi-yaml-2": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-parser-adapter-workflows-json-1": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-parser-adapter-workflows-yaml-1": "^1.0.0-beta.3 <1.0.0-rc.0",
- "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-beta.3 <1.0.0-rc.0"
+ "engines": {
+ "node": ">= 8"
}
},
- "node_modules/@swagger-api/apidom-reference/node_modules/brace-expansion": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "node_modules/csrf": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz",
+ "integrity": "sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w==",
"dependencies": {
- "balanced-match": "^1.0.0"
+ "rndm": "1.2.0",
+ "tsscmp": "1.0.6",
+ "uid-safe": "2.1.5"
+ },
+ "engines": {
+ "node": ">= 0.8"
}
},
- "node_modules/@swagger-api/apidom-reference/node_modules/minimatch": {
- "version": "7.4.6",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz",
- "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==",
+ "node_modules/css.escape": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
+ "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==",
+ "license": "MIT"
+ },
+ "node_modules/csurf": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.11.0.tgz",
+ "integrity": "sha512-UCtehyEExKTxgiu8UHdGvHj4tnpE/Qctue03Giq5gPgMQ9cg/ciod5blZQ5a4uCEenNQjxyGuzygLdKUmee/bQ==",
+ "deprecated": "This package is archived and no longer maintained. For support, visit https://github.com/expressjs/express/discussions",
"dependencies": {
- "brace-expansion": "^2.0.1"
+ "cookie": "0.4.0",
+ "cookie-signature": "1.0.6",
+ "csrf": "3.1.0",
+ "http-errors": "~1.7.3"
},
"engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "node": ">= 0.8.0"
}
},
- "node_modules/@swaggerexpert/cookie": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/@swaggerexpert/cookie/-/cookie-2.0.2.tgz",
- "integrity": "sha512-DPI8YJ0Vznk4CT+ekn3rcFNq1uQwvUHZhH6WvTSPD0YKBIlMS9ur2RYKghXuxxOiqOam/i4lHJH4xTIiTgs3Mg==",
+ "node_modules/csurf/node_modules/cookie": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+ "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/csurf/node_modules/depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/csurf/node_modules/http-errors": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
+ "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
"dependencies": {
- "apg-lite": "^1.0.3"
+ "depd": "~1.1.2",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.1.1",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.0"
},
"engines": {
- "node": ">=12.20.0"
+ "node": ">= 0.6"
}
},
- "node_modules/@tootallnate/quickjs-emscripten": {
- "version": "0.23.0",
- "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
- "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="
+ "node_modules/csurf/node_modules/setprototypeof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
},
- "node_modules/@types/estree": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
- "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
- "dev": true
+ "node_modules/csurf/node_modules/statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+ "engines": {
+ "node": ">= 0.6"
+ }
},
- "node_modules/@types/hast": {
- "version": "2.3.10",
- "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz",
- "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==",
- "dependencies": {
- "@types/unist": "^2"
+ "node_modules/csurf/node_modules/toidentifier": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
+ "engines": {
+ "node": ">=0.6"
}
},
- "node_modules/@types/json-schema": {
- "version": "7.0.15",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
- "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
+ "node_modules/culvert": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz",
+ "integrity": "sha512-yi1x3EAWKjQTreYWeSd98431AV+IEE0qoDyOoaHJ7KJ21gv6HtBXHVLX74opVSGqcR8/AbjJBHAHpcOy2bj5Gg==",
+ "license": "MIT"
},
- "node_modules/@types/ramda": {
- "version": "0.30.2",
- "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.30.2.tgz",
- "integrity": "sha512-PyzHvjCalm2BRYjAU6nIB3TprYwMNOUY/7P/N8bSzp9W/yM2YrtGtAnnVtaCNSeOZ8DzKyFDvaqQs7LnWwwmBA==",
+ "node_modules/data-uri-to-buffer": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
+ "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/date-fns": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
+ "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/kossnocorp"
+ }
+ },
+ "node_modules/dayjs": {
+ "version": "1.11.13",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
+ "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
"dependencies": {
- "types-ramda": "^0.30.1"
+ "ms": "2.0.0"
}
},
- "node_modules/@types/trusted-types": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
- "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
- "optional": true
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="
+ "node_modules/dedent": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz",
+ "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
},
- "node_modules/@types/use-sync-external-store": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
- "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg=="
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0.0"
+ }
},
- "node_modules/@types/uuid": {
- "version": "9.0.8",
- "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
- "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA=="
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "license": "MIT",
"dependencies": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
},
"engines": {
- "node": ">= 0.6"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/acorn": {
- "version": "8.14.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
- "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
- "dev": true,
- "bin": {
- "acorn": "bin/acorn"
+ "node_modules/degenerator": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
+ "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ast-types": "^0.13.4",
+ "escodegen": "^2.1.0",
+ "esprima": "^4.0.1"
},
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
- "node_modules/acorn-jsx": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
- "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true,
- "peerDependencies": {
- "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ "node_modules/denque": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
+ "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=0.10"
}
},
- "node_modules/agent-base": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
- "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "license": "MIT",
"engines": {
- "node": ">= 14"
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
}
},
- "node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "node_modules/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
"dev": true,
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/amp": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/amp/-/amp-0.3.1.tgz",
- "integrity": "sha512-OwIuC4yZaRogHKiuU5WlMR5Xk/jAcpPtawWL05Gj8Lvm2F6mwoJt4O/bHI+DHwG79vWd+8OFYM4/BzYqyRd3qw=="
- },
- "node_modules/amp-message": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/amp-message/-/amp-message-0.1.2.tgz",
- "integrity": "sha512-JqutcFwoU1+jhv7ArgW38bqrE+LQdcRv4NxNw0mp0JHQyB6tXesWRjtYKlDgHRY2o3JE5UTaBGUK8kSWUdxWUg==",
+ "node_modules/dezalgo": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
+ "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
+ "license": "ISC",
"dependencies": {
- "amp": "0.3.1"
+ "asap": "^2.0.0",
+ "wrappy": "1"
}
},
- "node_modules/ansi-colors": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
- "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "node_modules/diff-sequences": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=6"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "node_modules/dijkstrajs": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
+ "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==",
+ "license": "MIT"
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "license": "Apache-2.0",
"dependencies": {
- "color-convert": "^2.0.1"
+ "esutils": "^2.0.2"
},
"engines": {
- "node": ">=8"
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dompurify": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz",
+ "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==",
+ "license": "(MPL-2.0 OR Apache-2.0)",
+ "optionalDependencies": {
+ "@types/trusted-types": "^2.0.7"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "16.5.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz",
+ "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
},
"funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ "url": "https://dotenvx.com"
}
},
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "node_modules/drange": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz",
+ "integrity": "sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
"dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
},
"engines": {
- "node": ">= 8"
+ "node": ">= 0.4"
}
},
- "node_modules/apg-lite": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/apg-lite/-/apg-lite-1.0.4.tgz",
- "integrity": "sha512-B32zCN3IdHIc99Vy7V9BaYTUzLeRA8YXYY1aQD1/5I2aqIrO0coi4t6hJPqMisidlBxhyME8UexkHt31SlR6Og=="
- },
- "node_modules/append-field": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
- "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="
+ "node_modules/duplexer2": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
+ "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "readable-stream": "^2.0.2"
+ }
},
- "node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
},
- "node_modules/array-flatten": {
+ "node_modules/ee-first": {
"version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
},
- "node_modules/ast-types": {
- "version": "0.13.4",
- "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
- "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
- "dependencies": {
- "tslib": "^2.0.1"
- },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.152",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.152.tgz",
+ "integrity": "sha512-xBOfg/EBaIlVsHipHl2VdTPJRSvErNUaqW8ejTq5OlOlIYx1wOllCHsAvAIrr55jD1IYEfdR86miUEt8H5IeJg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/emittery": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=4"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
}
},
- "node_modules/async": {
- "version": "3.2.6",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
- "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
},
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
},
- "node_modules/autolinker": {
- "version": "3.16.2",
- "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-3.16.2.tgz",
- "integrity": "sha512-JiYl7j2Z19F9NdTmirENSUUIIL/9MytEWtmzhfmsKPCp9E+G35Y0UNCMoM9tFigxT59qSc8Ml2dlZXOCVTYwuA==",
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "license": "MIT",
"dependencies": {
- "tslib": "^2.3.0"
+ "once": "^1.4.0"
}
},
- "node_modules/available-typed-arrays": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
- "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "node_modules/enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "license": "MIT",
"dependencies": {
- "possible-typed-array-names": "^1.0.0"
+ "ansi-colors": "^4.1.1"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">=8.6"
}
},
- "node_modules/aws-sdk": {
- "version": "2.1692.0",
- "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1692.0.tgz",
- "integrity": "sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw==",
- "hasInstallScript": true,
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "buffer": "4.9.2",
- "events": "1.1.1",
- "ieee754": "1.1.13",
- "jmespath": "0.16.0",
- "querystring": "0.2.0",
- "sax": "1.2.1",
- "url": "0.10.3",
- "util": "^0.12.4",
- "uuid": "8.0.0",
- "xml2js": "0.6.2"
- },
- "engines": {
- "node": ">= 10.0.0"
+ "is-arrayish": "^0.2.1"
}
},
- "node_modules/aws-sdk/node_modules/sax": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
- "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA=="
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
},
- "node_modules/aws-sdk/node_modules/uuid": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz",
- "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==",
- "bin": {
- "uuid": "dist/bin/uuid"
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
}
},
- "node_modules/axios": {
- "version": "1.8.2",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.2.tgz",
- "integrity": "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==",
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
"dependencies": {
- "follow-redirects": "^1.15.6",
- "form-data": "^4.0.0",
- "proxy-from-env": "^1.1.0"
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
}
},
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
- },
- "node_modules/base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/basic-ftp": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
- "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
"engines": {
- "node": ">=10.0.0"
+ "node": ">= 0.4"
}
},
- "node_modules/bcryptjs": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.2.tgz",
- "integrity": "sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==",
- "bin": {
- "bcrypt": "bin/bcrypt"
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
}
},
- "node_modules/binary-extensions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
- "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT"
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/blessed": {
- "version": "0.1.81",
- "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz",
- "integrity": "sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==",
+ "node_modules/escodegen": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
+ "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esprima": "^4.0.1",
+ "estraverse": "^5.2.0",
+ "esutils": "^2.0.2"
+ },
"bin": {
- "blessed": "bin/tput.js"
+ "escodegen": "bin/escodegen.js",
+ "esgenerate": "bin/esgenerate.js"
},
"engines": {
- "node": ">= 0.8.0"
+ "node": ">=6.0"
+ },
+ "optionalDependencies": {
+ "source-map": "~0.6.1"
}
},
- "node_modules/bodec": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/bodec/-/bodec-0.1.0.tgz",
- "integrity": "sha512-Ylo+MAo5BDUq1KA3f3R/MFhh+g8cnHmo8bz3YPGhI1znrMaf77ol1sfvYJzsw3nTE+Y2GryfDxBaR+AqpAkEHQ=="
- },
- "node_modules/body-parser": {
- "version": "1.20.3",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
- "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
+ "node_modules/eslint": {
+ "version": "9.26.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.26.0.tgz",
+ "integrity": "sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "bytes": "3.1.2",
- "content-type": "~1.0.5",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "1.2.0",
- "http-errors": "2.0.0",
- "iconv-lite": "0.4.24",
- "on-finished": "2.4.1",
- "qs": "6.13.0",
- "raw-body": "2.5.2",
- "type-is": "~1.6.18",
- "unpipe": "1.0.0"
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.20.0",
+ "@eslint/config-helpers": "^0.2.1",
+ "@eslint/core": "^0.13.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.26.0",
+ "@eslint/plugin-kit": "^0.2.8",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@modelcontextprotocol/sdk": "^1.8.0",
+ "@types/estree": "^1.0.6",
+ "@types/json-schema": "^7.0.15",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.3.0",
+ "eslint-visitor-keys": "^4.2.0",
+ "espree": "^10.3.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "zod": "^3.24.2"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
},
"engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
- },
- "node_modules/bowser": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
- "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA=="
- },
- "node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
}
},
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "node_modules/eslint-plugin-jsdoc": {
+ "version": "50.6.14",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.14.tgz",
+ "integrity": "sha512-JUudvooQbUx3iB8n/MzXMOV/VtaXq7xL4CeXhYryinr8osck7nV6fE2/xUXTiH3epPXcvq6TE3HQfGQuRHErTQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "fill-range": "^7.1.1"
+ "@es-joy/jsdoccomment": "~0.49.0",
+ "are-docs-informative": "^0.0.2",
+ "comment-parser": "1.4.1",
+ "debug": "^4.3.6",
+ "escape-string-regexp": "^4.0.0",
+ "espree": "^10.1.0",
+ "esquery": "^1.6.0",
+ "parse-imports-exports": "^0.2.4",
+ "semver": "^7.6.3",
+ "spdx-expression-parse": "^4.0.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
}
},
- "node_modules/buffer": {
- "version": "4.9.2",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
- "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
+ "node_modules/eslint-plugin-jsdoc/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "base64-js": "^1.0.2",
- "ieee754": "^1.1.4",
- "isarray": "^1.0.0"
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/buffer-equal-constant-time": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
- "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
- },
- "node_modules/buffer-from": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
+ "node_modules/eslint-plugin-jsdoc/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/busboy": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
- "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "node_modules/eslint-scope": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
+ "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "streamsearch": "^1.1.0"
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
},
"engines": {
- "node": ">=10.16.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
+ "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
+ "dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">= 0.8"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/call-bind": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
- "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+ "node_modules/eslint/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind-apply-helpers": "^1.0.0",
- "es-define-property": "^1.0.0",
- "get-intrinsic": "^1.2.4",
- "set-function-length": "^1.2.2"
+ "ms": "^2.1.3"
},
"engines": {
- "node": ">= 0.4"
+ "node": ">=6.0"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/call-bind-apply-helpers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
- "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "node_modules/eslint/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/espree": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
+ "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
+ "acorn": "^8.14.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/call-bound": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
- "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "get-intrinsic": "^1.3.0"
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">=4"
}
},
- "node_modules/call-me-maybe": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
- "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ=="
- },
- "node_modules/callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
"dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
"engines": {
- "node": ">=6"
+ "node": ">=0.10"
}
},
- "node_modules/chalk": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
- "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
+ "estraverse": "^5.2.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=4.0"
}
},
- "node_modules/character-entities": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
- "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
}
},
- "node_modules/character-entities-legacy": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
- "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "node_modules/character-reference-invalid": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
- "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
}
},
- "node_modules/charm": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz",
- "integrity": "sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ=="
+ "node_modules/eventemitter2": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz",
+ "integrity": "sha512-5EM1GHXycJBS6mauYAbVKT1cVs7POKWb2NXD4Vyt8dDqeZa7LaDK1/sjtL+Zb0lzTpSNil4596Dyu97hz37QLg==",
+ "license": "MIT"
},
- "node_modules/chokidar": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
- "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "node_modules/events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "node_modules/eventsource": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz",
+ "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "anymatch": "~3.1.2",
- "braces": "~3.0.2",
- "glob-parent": "~5.1.2",
- "is-binary-path": "~2.1.0",
- "is-glob": "~4.0.1",
- "normalize-path": "~3.0.0",
- "readdirp": "~3.6.0"
+ "eventsource-parser": "^3.0.1"
},
"engines": {
- "node": ">= 8.10.0"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
+ "node": ">=18.0.0"
}
},
- "node_modules/classnames": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
- "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
+ "node_modules/eventsource-parser": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz",
+ "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ }
},
- "node_modules/cli-tableau": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/cli-tableau/-/cli-tableau-2.0.1.tgz",
- "integrity": "sha512-he+WTicka9cl0Fg/y+YyxcN6/bfQ/1O3QmgxRXDhABKqLzvoOSM4fMzp39uMyLBulAFuywD2N7UaoQE7WaADxQ==",
+ "node_modules/exceljs": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/exceljs/-/exceljs-4.4.0.tgz",
+ "integrity": "sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg==",
+ "license": "MIT",
"dependencies": {
- "chalk": "3.0.0"
+ "archiver": "^5.0.0",
+ "dayjs": "^1.8.34",
+ "fast-csv": "^4.3.1",
+ "jszip": "^3.10.1",
+ "readable-stream": "^3.6.0",
+ "saxes": "^5.0.1",
+ "tmp": "^0.2.0",
+ "unzipper": "^0.10.11",
+ "uuid": "^8.3.0"
},
"engines": {
- "node": ">=8.10.0"
+ "node": ">=8.3.0"
}
},
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "node_modules/exceljs/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
"dependencies": {
- "color-name": "~1.1.4"
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
},
"engines": {
- "node": ">=7.0.0"
+ "node": ">= 6"
}
},
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ "node_modules/exceljs/node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
},
- "node_modules/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dependencies": {
- "delayed-stream": "~1.0.0"
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
},
"engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/comma-separated-tokens": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz",
- "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==",
+ "node": ">=10"
+ },
"funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
- "node_modules/commander": {
- "version": "2.15.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
- "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag=="
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ "node_modules/exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
},
- "node_modules/concat-stream": {
- "version": "1.6.2",
- "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
- "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
- "engines": [
- "node >= 0.8"
- ],
+ "node_modules/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "buffer-from": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^2.2.2",
- "typedarray": "^0.0.6"
+ "@jest/expect-utils": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/content-disposition": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
- "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "node_modules/express": {
+ "version": "4.21.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
+ "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
+ "license": "MIT",
"dependencies": {
- "safe-buffer": "5.2.1"
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.20.3",
+ "content-disposition": "0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "0.7.1",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.3.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "merge-descriptors": "1.0.3",
+ "methods": "~1.1.2",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.12",
+ "proxy-addr": "~2.0.7",
+ "qs": "6.13.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "0.19.0",
+ "serve-static": "1.16.2",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
},
"engines": {
- "node": ">= 0.6"
+ "node": ">= 0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "node_modules/express-rate-limit": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz",
+ "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">= 0.6"
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/express-rate-limit"
+ },
+ "peerDependencies": {
+ "express": "^4.11 || 5 || ^5.0.0-beta.1"
}
},
- "node_modules/cookie": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
- "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "node_modules/express/node_modules/cookie": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
+ "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
- "node_modules/cookie-parser": {
- "version": "1.4.7",
- "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
- "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
+ "node_modules/extrareqp2": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/extrareqp2/-/extrareqp2-1.0.0.tgz",
+ "integrity": "sha512-Gum0g1QYb6wpPJCVypWP3bbIuaibcFiJcpuPM10YSXp/tzqi84x9PJageob+eN4xVRIOto4wjSGNLyMD54D2xA==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.14.0"
+ }
+ },
+ "node_modules/fast-csv": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz",
+ "integrity": "sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==",
+ "license": "MIT",
"dependencies": {
- "cookie": "0.7.2",
- "cookie-signature": "1.0.6"
+ "@fast-csv/format": "4.3.5",
+ "@fast-csv/parse": "4.3.6"
},
"engines": {
- "node": ">= 0.8.0"
+ "node": ">=10.0.0"
}
},
- "node_modules/cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/copy-to-clipboard": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
- "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==",
- "dependencies": {
- "toggle-selection": "^1.0.6"
- }
+ "node_modules/fast-json-patch": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz",
+ "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==",
+ "license": "MIT"
},
- "node_modules/core-js-pure": {
- "version": "3.41.0",
- "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.41.0.tgz",
- "integrity": "sha512-71Gzp96T9YPk63aUvE5Q5qP+DryB4ZloUZPSOebGM88VNw8VNfvdA7z6kGA8iGOTEzAomsRidp4jXSmUIJsL+Q==",
- "hasInstallScript": true,
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/core-js"
- }
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/core-util-is": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
- "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/cors": {
- "version": "2.8.5",
- "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
- "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+ "node_modules/fast-safe-stringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
+ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
+ "license": "MIT"
+ },
+ "node_modules/fast-xml-parser": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz",
+ "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/naturalintelligence"
+ }
+ ],
+ "license": "MIT",
"dependencies": {
- "object-assign": "^4",
- "vary": "^1"
+ "strnum": "^1.0.5"
},
- "engines": {
- "node": ">= 0.10"
+ "bin": {
+ "fxparser": "src/cli/cli.js"
}
},
- "node_modules/croner": {
- "version": "4.1.97",
- "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz",
- "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ=="
- },
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
- "dev": true,
+ "node_modules/fault": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz",
+ "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==",
+ "license": "MIT",
"dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
+ "format": "^0.2.0"
},
- "engines": {
- "node": ">= 8"
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/css.escape": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
- "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg=="
- },
- "node_modules/culvert": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz",
- "integrity": "sha512-yi1x3EAWKjQTreYWeSd98431AV+IEE0qoDyOoaHJ7KJ21gv6HtBXHVLX74opVSGqcR8/AbjJBHAHpcOy2bj5Gg=="
- },
- "node_modules/data-uri-to-buffer": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
- "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
- "engines": {
- "node": ">= 14"
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bser": "2.1.1"
}
},
- "node_modules/dayjs": {
- "version": "1.11.13",
- "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
- "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
+ "node_modules/fclone": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz",
+ "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==",
+ "license": "MIT"
},
- "node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/deep-extend": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "flat-cache": "^4.0.0"
+ },
"engines": {
- "node": ">=4.0.0"
+ "node": ">=16.0.0"
}
},
- "node_modules/deep-is": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
- "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "dev": true
- },
- "node_modules/deepmerge": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
- "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "node_modules/file-type": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
+ "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/define-data-property": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
- "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "license": "MIT",
"dependencies": {
- "es-define-property": "^1.0.0",
- "es-errors": "^1.3.0",
- "gopd": "^1.0.1"
+ "to-regex-range": "^5.0.1"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">=8"
}
},
- "node_modules/degenerator": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
- "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
+ "node_modules/finalhandler": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
+ "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
+ "license": "MIT",
"dependencies": {
- "ast-types": "^0.13.4",
- "escodegen": "^2.1.0",
- "esprima": "^4.0.1"
+ "debug": "2.6.9",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "2.0.1",
+ "unpipe": "~1.0.0"
},
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"engines": {
"node": ">= 0.8"
}
},
- "node_modules/destroy": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
- "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
"engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "esutils": "^2.0.2"
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
},
"engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/dompurify": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz",
- "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==",
- "optionalDependencies": {
- "@types/trusted-types": "^2.0.7"
+ "node": ">=16"
}
},
- "node_modules/dotenv": {
- "version": "16.4.7",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
- "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://dotenvx.com"
- }
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
},
- "node_modules/drange": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz",
- "integrity": "sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==",
+ "node_modules/follow-redirects": {
+ "version": "1.15.9",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
"engines": {
- "node": ">=4"
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
}
},
- "node_modules/dunder-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
- "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "node_modules/for-each": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+ "license": "MIT",
"dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "es-errors": "^1.3.0",
- "gopd": "^1.2.0"
+ "is-callable": "^1.2.7"
},
"engines": {
"node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/ecdsa-sig-formatter": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
- "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "node_modules/form-data": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
+ "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
+ "license": "MIT",
"dependencies": {
- "safe-buffer": "^5.0.1"
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
}
},
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
- },
- "node_modules/encodeurl": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
- "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "node_modules/format": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
+ "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==",
"engines": {
- "node": ">= 0.8"
+ "node": ">=0.4.x"
}
},
- "node_modules/enquirer": {
- "version": "2.3.6",
- "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
- "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "node_modules/formidable": {
+ "version": "3.5.4",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz",
+ "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==",
+ "license": "MIT",
"dependencies": {
- "ansi-colors": "^4.1.1"
+ "@paralleldrive/cuid2": "^2.2.2",
+ "dezalgo": "^1.0.4",
+ "once": "^1.4.0"
},
"engines": {
- "node": ">=8.6"
+ "node": ">=14.0.0"
+ },
+ "funding": {
+ "url": "https://ko-fi.com/tunnckoCore/commissions"
}
},
- "node_modules/es-define-property": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
"engines": {
- "node": ">= 0.4"
+ "node": ">= 0.6"
}
},
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "license": "MIT",
"engines": {
- "node": ">= 0.4"
+ "node": ">= 0.6"
}
},
- "node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
- "dependencies": {
- "es-errors": "^1.3.0"
- },
+ "node_modules/fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+ "license": "MIT"
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
"engines": {
- "node": ">= 0.4"
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
- "node_modules/es-set-tostringtag": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
- "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "node_modules/fstream": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
+ "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+ "deprecated": "This package is no longer supported.",
+ "license": "ISC",
"dependencies": {
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
+ "graceful-fs": "^4.1.2",
+ "inherits": "~2.0.0",
+ "mkdirp": ">=0.5 0",
+ "rimraf": "2"
},
"engines": {
- "node": ">= 0.4"
+ "node": ">=0.6"
}
},
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
- },
- "node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "engines": {
- "node": ">=10"
- },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/escodegen": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
- "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
+ "node_modules/generate-function": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
+ "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
+ "license": "MIT",
"dependencies": {
- "esprima": "^4.0.1",
- "estraverse": "^5.2.0",
- "esutils": "^2.0.2"
- },
- "bin": {
- "escodegen": "bin/escodegen.js",
- "esgenerate": "bin/esgenerate.js"
- },
- "engines": {
- "node": ">=6.0"
- },
- "optionalDependencies": {
- "source-map": "~0.6.1"
+ "is-property": "^1.0.2"
}
},
- "node_modules/eslint": {
- "version": "9.22.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz",
- "integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==",
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
"dev": true,
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.2.0",
- "@eslint-community/regexpp": "^4.12.1",
- "@eslint/config-array": "^0.19.2",
- "@eslint/config-helpers": "^0.1.0",
- "@eslint/core": "^0.12.0",
- "@eslint/eslintrc": "^3.3.0",
- "@eslint/js": "9.22.0",
- "@eslint/plugin-kit": "^0.2.7",
- "@humanfs/node": "^0.16.6",
- "@humanwhocodes/module-importer": "^1.0.1",
- "@humanwhocodes/retry": "^0.4.2",
- "@types/estree": "^1.0.6",
- "@types/json-schema": "^7.0.15",
- "ajv": "^6.12.4",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.6",
- "debug": "^4.3.2",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^8.3.0",
- "eslint-visitor-keys": "^4.2.0",
- "espree": "^10.3.0",
- "esquery": "^1.5.0",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^8.0.0",
- "find-up": "^5.0.0",
- "glob-parent": "^6.0.2",
- "ignore": "^5.2.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "lodash.merge": "^4.6.2",
- "minimatch": "^3.1.2",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.3"
- },
- "bin": {
- "eslint": "bin/eslint.js"
- },
+ "license": "MIT",
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://eslint.org/donate"
- },
- "peerDependencies": {
- "jiti": "*"
- },
- "peerDependenciesMeta": {
- "jiti": {
- "optional": true
- }
+ "node": ">=6.9.0"
}
},
- "node_modules/eslint-scope": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
- "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
- "dev": true,
- "dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
- },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "license": "ISC",
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "node": "6.* || 8.* || >= 10.*"
}
},
- "node_modules/eslint-visitor-keys": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
- "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
- "dev": true,
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">= 0.4"
},
"funding": {
- "url": "https://opencollective.com/eslint"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/eslint/node_modules/@eslint/js": {
- "version": "9.22.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz",
- "integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==",
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">=8.0.0"
}
},
- "node_modules/eslint/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
"dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
},
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/eslint/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
- "dev": true,
+ "node_modules/get-uri": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz",
+ "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "basic-ftp": "^5.0.2",
+ "data-uri-to-buffer": "^6.0.2",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/get-uri/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
@@ -3853,11 +7540,51 @@
}
}
},
- "node_modules/eslint/node_modules/glob-parent": {
+ "node_modules/get-uri/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/git-node-fs": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/git-node-fs/-/git-node-fs-1.0.0.tgz",
+ "integrity": "sha512-bLQypt14llVXBg0S0u8q8HmU7g9p3ysH+NvVlae5vILuUvs759665HvmR5+wb04KjHyjFcDRxdYb4kyNnluMUQ==",
+ "license": "MIT"
+ },
+ "node_modules/git-sha1": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/git-sha1/-/git-sha1-0.1.2.tgz",
+ "integrity": "sha512-2e/nZezdVlyCopOCYHeW0onkbZg7xP1Ad6pndPy1rCygeRykefUS6r7oA5cJRGEFvseiaz5a/qUHFVX1dd6Isg==",
+ "license": "MIT"
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"is-glob": "^4.0.3"
},
@@ -3865,332 +7592,455 @@
"node": ">=10.13.0"
}
},
- "node_modules/eslint/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true
- },
- "node_modules/espree": {
- "version": "10.3.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
- "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
+ "node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
"dev": true,
- "dependencies": {
- "acorn": "^8.14.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^4.2.0"
- },
+ "license": "MIT",
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">=18"
},
"funding": {
- "url": "https://opencollective.com/eslint"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/esprima": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
- "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
- "bin": {
- "esparse": "bin/esparse.js",
- "esvalidate": "bin/esvalidate.js"
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
},
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "license": "ISC"
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
"engines": {
- "node": ">=4"
+ "node": ">=8"
}
},
- "node_modules/esquery": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
- "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
- "dev": true,
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "license": "MIT",
"dependencies": {
- "estraverse": "^5.1.0"
+ "es-define-property": "^1.0.0"
},
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
"engines": {
- "node": ">=0.10"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
"dependencies": {
- "estraverse": "^5.2.0"
+ "has-symbols": "^1.0.3"
},
"engines": {
- "node": ">=4.0"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
"engines": {
- "node": ">=4.0"
+ "node": ">= 0.4"
}
},
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "engines": {
- "node": ">=0.10.0"
+ "node_modules/hast-util-parse-selector": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz",
+ "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
- "engines": {
- "node": ">= 0.6"
+ "node_modules/hastscript": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz",
+ "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^2.0.0",
+ "comma-separated-tokens": "^1.0.0",
+ "hast-util-parse-selector": "^2.0.0",
+ "property-information": "^5.0.0",
+ "space-separated-tokens": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/eventemitter2": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz",
- "integrity": "sha512-5EM1GHXycJBS6mauYAbVKT1cVs7POKWb2NXD4Vyt8dDqeZa7LaDK1/sjtL+Zb0lzTpSNil4596Dyu97hz37QLg=="
+ "node_modules/helmet": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.1.0.tgz",
+ "integrity": "sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ }
},
- "node_modules/events": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
- "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==",
+ "node_modules/highlight.js": {
+ "version": "10.7.3",
+ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
+ "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
+ "license": "BSD-3-Clause",
"engines": {
- "node": ">=0.4.x"
+ "node": "*"
}
},
- "node_modules/express": {
- "version": "4.21.2",
- "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
- "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
- "dependencies": {
- "accepts": "~1.3.8",
- "array-flatten": "1.1.1",
- "body-parser": "1.20.3",
- "content-disposition": "0.5.4",
- "content-type": "~1.0.4",
- "cookie": "0.7.1",
- "cookie-signature": "1.0.6",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "finalhandler": "1.3.1",
- "fresh": "0.5.2",
- "http-errors": "2.0.0",
- "merge-descriptors": "1.0.3",
- "methods": "~1.1.2",
- "on-finished": "2.4.1",
- "parseurl": "~1.3.3",
- "path-to-regexp": "0.1.12",
- "proxy-addr": "~2.0.7",
- "qs": "6.13.0",
- "range-parser": "~1.2.1",
- "safe-buffer": "5.2.1",
- "send": "0.19.0",
- "serve-static": "1.16.2",
+ "node_modules/highlightjs-vue": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz",
+ "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==",
+ "license": "CC0-1.0"
+ },
+ "node_modules/html-comment-regex": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz",
+ "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==",
+ "license": "MIT"
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
- "type-is": "~1.6.18",
- "utils-merge": "1.0.1",
- "vary": "~1.1.2"
+ "toidentifier": "1.0.1"
},
"engines": {
- "node": ">= 0.10.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
+ "node": ">= 0.8"
}
},
- "node_modules/express/node_modules/cookie": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
- "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
+ "node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
+ },
"engines": {
- "node": ">= 0.6"
+ "node": ">= 14"
}
},
- "node_modules/extrareqp2": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/extrareqp2/-/extrareqp2-1.0.0.tgz",
- "integrity": "sha512-Gum0g1QYb6wpPJCVypWP3bbIuaibcFiJcpuPM10YSXp/tzqi84x9PJageob+eN4xVRIOto4wjSGNLyMD54D2xA==",
+ "node_modules/http-proxy-agent/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
"dependencies": {
- "follow-redirects": "^1.14.0"
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
- },
- "node_modules/fast-json-patch": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz",
- "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ=="
- },
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true
- },
- "node_modules/fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
- "dev": true
+ "node_modules/http-proxy-agent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
},
- "node_modules/fast-xml-parser": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz",
- "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/NaturalIntelligence"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/naturalintelligence"
- }
- ],
+ "node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
"dependencies": {
- "strnum": "^1.0.5"
+ "agent-base": "^7.1.2",
+ "debug": "4"
},
- "bin": {
- "fxparser": "src/cli/cli.js"
+ "engines": {
+ "node": ">= 14"
}
},
- "node_modules/fault": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz",
- "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==",
+ "node_modules/https-proxy-agent/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
"dependencies": {
- "format": "^0.2.0"
+ "ms": "^2.1.3"
},
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/fclone": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz",
- "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw=="
+ "node_modules/https-proxy-agent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
},
- "node_modules/file-entry-cache": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
- "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
"dev": true,
- "dependencies": {
- "flat-cache": "^4.0.0"
- },
+ "license": "Apache-2.0",
"engines": {
- "node": ">=16.0.0"
+ "node": ">=10.17.0"
}
},
- "node_modules/file-type": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
- "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==",
+ "node_modules/i": {
+ "version": "0.3.7",
+ "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz",
+ "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=0.4"
}
},
- "node_modules/fill-range": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "license": "MIT",
"dependencies": {
- "to-regex-range": "^5.0.1"
+ "safer-buffer": ">= 2.1.2 < 3"
},
"engines": {
- "node": ">=8"
+ "node": ">=0.10.0"
}
},
- "node_modules/finalhandler": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
- "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
+ "node_modules/ieee754": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/ignore-by-default": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
+ "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
+ "license": "ISC"
+ },
+ "node_modules/immediate": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
+ "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
+ "license": "MIT"
+ },
+ "node_modules/immutable": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz",
+ "integrity": "sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "debug": "2.6.9",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "on-finished": "2.4.1",
- "parseurl": "~1.3.3",
- "statuses": "2.0.1",
- "unpipe": "~1.0.0"
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
},
"engines": {
- "node": ">= 0.8"
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/find-up": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "node_modules/import-local": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
+ "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
},
"engines": {
- "node": ">=10"
+ "node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/flat-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
- "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
"dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "license": "ISC",
"dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.4"
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "license": "ISC"
+ },
+ "node_modules/invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "node_modules/ip-address": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
+ "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
+ "license": "MIT",
+ "dependencies": {
+ "jsbn": "1.1.0",
+ "sprintf-js": "^1.1.3"
},
"engines": {
- "node": ">=16"
+ "node": ">= 12"
}
},
- "node_modules/flatted": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
- "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
- "dev": true
+ "node_modules/ip-address/node_modules/sprintf-js": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
+ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
+ "license": "BSD-3-Clause"
},
- "node_modules/follow-redirects": {
- "version": "1.15.9",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
- "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
- "funding": [
- {
- "type": "individual",
- "url": "https://github.com/sponsors/RubenVerborgh"
- }
- ],
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "license": "MIT",
"engines": {
- "node": ">=4.0"
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-alphabetical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
+ "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-alphanumerical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
+ "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
+ "license": "MIT",
+ "dependencies": {
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0"
},
- "peerDependenciesMeta": {
- "debug": {
- "optional": true
- }
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/for-each": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
- "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+ "node_modules/is-arguments": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
+ "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
+ "license": "MIT",
"dependencies": {
- "is-callable": "^1.2.7"
+ "call-bound": "^1.0.2",
+ "has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -4199,85 +8049,44 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/form-data": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
- "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "license": "MIT",
"dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.8",
- "es-set-tostringtag": "^2.1.0",
- "mime-types": "^2.1.12"
+ "binary-extensions": "^2.0.0"
},
"engines": {
- "node": ">= 6"
- }
- },
- "node_modules/format": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
- "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==",
- "engines": {
- "node": ">=0.4.x"
- }
- },
- "node_modules/forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
- "engines": {
- "node": ">= 0.6"
+ "node": ">=8"
}
},
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "license": "MIT",
"engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "node": ">= 0.4"
+ },
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/get-intrinsic": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
- "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "node_modules/is-core-module": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "license": "MIT",
"dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "function-bind": "^1.1.2",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "math-intrinsics": "^1.1.0"
+ "hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -4286,152 +8095,144 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/get-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
- "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
- "dependencies": {
- "dunder-proto": "^1.0.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
+ "node_modules/is-decimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
+ "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/get-uri": {
- "version": "6.0.4",
- "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz",
- "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==",
- "dependencies": {
- "basic-ftp": "^5.0.2",
- "data-uri-to-buffer": "^6.0.2",
- "debug": "^4.3.4"
- },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "license": "MIT",
"engines": {
- "node": ">= 14"
+ "node": ">=0.10.0"
}
},
- "node_modules/get-uri/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
- "dependencies": {
- "ms": "^2.1.3"
- },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
"engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
+ "node": ">=8"
}
},
- "node_modules/get-uri/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
- },
- "node_modules/git-node-fs": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/git-node-fs/-/git-node-fs-1.0.0.tgz",
- "integrity": "sha512-bLQypt14llVXBg0S0u8q8HmU7g9p3ysH+NvVlae5vILuUvs759665HvmR5+wb04KjHyjFcDRxdYb4kyNnluMUQ=="
- },
- "node_modules/git-sha1": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/git-sha1/-/git-sha1-0.1.2.tgz",
- "integrity": "sha512-2e/nZezdVlyCopOCYHeW0onkbZg7xP1Ad6pndPy1rCygeRykefUS6r7oA5cJRGEFvseiaz5a/qUHFVX1dd6Isg=="
+ "node_modules/is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
},
- "node_modules/glob": {
- "version": "7.1.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
+ "node_modules/is-generator-function": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
+ "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
+ "license": "MIT",
"dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.0",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
},
"engines": {
- "node": "*"
+ "node": ">= 0.4"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "license": "MIT",
"dependencies": {
- "is-glob": "^4.0.1"
+ "is-extglob": "^2.1.1"
},
"engines": {
- "node": ">= 6"
+ "node": ">=0.10.0"
}
},
- "node_modules/globals": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
- "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
- "dev": true,
- "engines": {
- "node": ">=18"
- },
+ "node_modules/is-hexadecimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
+ "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
+ "license": "MIT",
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/gopd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "license": "MIT",
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">=0.12.0"
}
},
- "node_modules/has-flag": {
+ "node_modules/is-promise": {
"version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "engines": {
- "node": ">=8"
- }
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
+ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/has-property-descriptors": {
+ "node_modules/is-property": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
- "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
+ "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==",
+ "license": "MIT"
+ },
+ "node_modules/is-regex": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
+ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
+ "license": "MIT",
"dependencies": {
- "es-define-property": "^1.0.0"
+ "call-bound": "^1.0.2",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/has-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">= 0.4"
+ "node": ">=8"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/has-tostringtag": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
- "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "node_modules/is-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+ "license": "MIT",
"dependencies": {
- "has-symbols": "^1.0.3"
+ "which-typed-array": "^1.1.16"
},
"engines": {
"node": ">= 0.4"
@@ -4440,91 +8241,82 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "license": "MIT"
},
- "node_modules/hast-util-parse-selector": {
- "version": "2.2.5",
- "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz",
- "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/hastscript": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz",
- "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==",
+ "node_modules/istanbul-lib-instrument": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
+ "dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "@types/hast": "^2.0.0",
- "comma-separated-tokens": "^1.0.0",
- "hast-util-parse-selector": "^2.0.0",
- "property-information": "^5.0.0",
- "space-separated-tokens": "^1.0.0"
+ "@babel/core": "^7.23.9",
+ "@babel/parser": "^7.23.9",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^7.5.4"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/highlight.js": {
- "version": "10.7.3",
- "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
- "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
"engines": {
- "node": "*"
+ "node": ">=10"
}
},
- "node_modules/highlightjs-vue": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz",
- "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA=="
- },
- "node_modules/html-comment-regex": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz",
- "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ=="
- },
- "node_modules/http-errors": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
- "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "depd": "2.0.0",
- "inherits": "2.0.4",
- "setprototypeof": "1.2.0",
- "statuses": "2.0.1",
- "toidentifier": "1.0.1"
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
},
"engines": {
- "node": ">= 0.8"
+ "node": ">=10"
}
},
- "node_modules/http-proxy-agent": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
- "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "agent-base": "^7.1.0",
- "debug": "^4.3.4"
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
},
"engines": {
- "node": ">= 14"
+ "node": ">=10"
}
},
- "node_modules/http-proxy-agent/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "node_modules/istanbul-lib-source-maps/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
@@ -4537,336 +8329,615 @@
}
}
},
- "node_modules/http-proxy-agent/node_modules/ms": {
+ "node_modules/istanbul-lib-source-maps/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/https-proxy-agent": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
- "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "node_modules/istanbul-reports": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
+ "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "agent-base": "^7.1.2",
- "debug": "4"
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
},
"engines": {
- "node": ">= 14"
+ "node": ">=8"
}
},
- "node_modules/https-proxy-agent/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "node_modules/jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
+ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "ms": "^2.1.3"
+ "@jest/core": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.7.0"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
},
"engines": {
- "node": ">=6.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
},
"peerDependenciesMeta": {
- "supports-color": {
+ "node-notifier": {
"optional": true
}
}
},
- "node_modules/https-proxy-agent/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
- },
- "node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "node_modules/jest-changed-files": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
+ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
+ "execa": "^5.0.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/ieee754": {
- "version": "1.1.13",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
- "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
- },
- "node_modules/ignore": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
- "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "node_modules/jest-circus": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
+ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
"dev": true,
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/immutable": {
- "version": "3.8.2",
- "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz",
- "integrity": "sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/import-fresh": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
- "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^1.0.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.7.0",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.7.0",
+ "pure-rand": "^6.0.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-cli": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
+ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
+ "@jest/core": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "create-jest": "^29.7.0",
+ "exit": "^0.1.2",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "yargs": "^17.3.1"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
},
"engines": {
- "node": ">=6"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
}
},
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "node_modules/jest-config": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
+ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
"dev": true,
- "engines": {
- "node": ">=0.8.19"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "license": "MIT",
"dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-jest": "^29.7.0",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-circus": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
}
},
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- },
- "node_modules/ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
- },
- "node_modules/invariant": {
- "version": "2.2.4",
- "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
- "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "node_modules/jest-diff": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "loose-envify": "^1.0.0"
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/ip-address": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
- "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
+ "node_modules/jest-docblock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
+ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "jsbn": "1.1.0",
- "sprintf-js": "^1.1.3"
+ "detect-newline": "^3.0.0"
},
"engines": {
- "node": ">= 12"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/ip-address/node_modules/sprintf-js": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
- "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="
+ "node_modules/jest-each": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
+ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
},
- "node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "node_modules/jest-environment-node": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
"engines": {
- "node": ">= 0.10"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-alphabetical": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
- "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "node_modules/jest-get-type": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-alphanumerical": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
- "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
+ "node_modules/jest-haste-map": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "is-alphabetical": "^1.0.0",
- "is-decimal": "^1.0.0"
+ "@jest/types": "^29.6.3",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
},
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
}
},
- "node_modules/is-arguments": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
- "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
+ "node_modules/jest-leak-detector": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
+ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
- "has-tostringtag": "^1.0.2"
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "node_modules/jest-matcher-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "binary-extensions": "^2.0.0"
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
},
"engines": {
- "node": ">=8"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-callable": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "engines": {
- "node": ">= 0.4"
+ "node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-core-module": {
- "version": "2.16.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
- "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "hasown": "^2.0.2"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-pnp-resolver": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "peerDependencies": {
+ "jest-resolve": "*"
+ },
+ "peerDependenciesMeta": {
+ "jest-resolve": {
+ "optional": true
+ }
}
},
- "node_modules/is-decimal": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
- "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "node_modules/jest-resolve": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
+ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "resolve": "^1.20.0",
+ "resolve.exports": "^2.0.0",
+ "slash": "^3.0.0"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-generator-function": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
- "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
+ "node_modules/jest-resolve-dependencies": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
+ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3",
- "get-proto": "^1.0.0",
- "has-tostringtag": "^1.0.2",
- "safe-regex-test": "^1.1.0"
+ "jest-regex-util": "^29.6.3",
+ "jest-snapshot": "^29.7.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
+ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/environment": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-leak-detector": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-resolve": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runtime": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
+ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/globals": "^29.7.0",
+ "@jest/source-map": "^29.6.3",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^1.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
+ "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@babel/generator": "^7.7.2",
+ "@babel/plugin-syntax-jsx": "^7.7.2",
+ "@babel/plugin-syntax-typescript": "^7.7.2",
+ "@babel/types": "^7.3.3",
+ "@jest/expect-utils": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.7.0",
+ "semver": "^7.5.3"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "is-extglob": "^2.1.1"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
"engines": {
- "node": ">=0.10.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-hexadecimal": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
- "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "node_modules/jest-validate": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "node_modules/jest-validate/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=0.12.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/is-regex": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
- "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
+ "node_modules/jest-watcher": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
+ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
- "gopd": "^1.2.0",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.7.0",
+ "string-length": "^4.0.1"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/is-typed-array": {
- "version": "1.1.15",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
- "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "which-typed-array": "^1.1.16"
+ "has-flag": "^4.0.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
- "node_modules/isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true
- },
"node_modules/jmespath": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz",
"integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==",
+ "license": "Apache-2.0",
"engines": {
"node": ">= 0.6.0"
}
@@ -4874,12 +8945,14 @@
"node_modules/js-file-download": {
"version": "0.4.12",
"resolved": "https://registry.npmjs.org/js-file-download/-/js-file-download-0.4.12.tgz",
- "integrity": "sha512-rML+NkoD08p5Dllpjo0ffy4jRHeY6Zsapvr/W86N7E0yuzAO6qa5X9+xog6zQNlH102J7IXljNY2FtS6Lj3ucg=="
+ "integrity": "sha512-rML+NkoD08p5Dllpjo0ffy4jRHeY6Zsapvr/W86N7E0yuzAO6qa5X9+xog6zQNlH102J7IXljNY2FtS6Lj3ucg==",
+ "license": "MIT"
},
"node_modules/js-git": {
"version": "0.7.8",
"resolved": "https://registry.npmjs.org/js-git/-/js-git-0.7.8.tgz",
"integrity": "sha512-+E5ZH/HeRnoc/LW0AmAyhU+mNcWBzAKE+30+IDMLSLbbK+Tdt02AdkOKq9u15rlJsDEGFqtgckc8ZM59LhhiUA==",
+ "license": "MIT",
"dependencies": {
"bodec": "^0.1.0",
"culvert": "^0.1.2",
@@ -4890,12 +8963,14 @@
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "license": "MIT"
},
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
@@ -4906,36 +8981,110 @@
"node_modules/jsbn": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
- "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
+ "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
+ "license": "MIT"
+ },
+ "node_modules/jsdoc-type-pratt-parser": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz",
+ "integrity": "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
},
"node_modules/json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
+ "license": "ISC",
"optional": true
},
+ "node_modules/json2csv": {
+ "version": "6.0.0-alpha.2",
+ "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-6.0.0-alpha.2.tgz",
+ "integrity": "sha512-nJ3oP6QxN8z69IT1HmrJdfVxhU1kLTBVgMfRnNZc37YEY+jZ4nU27rBGxT4vaqM/KUCavLRhntmTuBFqZLBUcA==",
+ "dependencies": {
+ "@streamparser/json": "^0.0.6",
+ "commander": "^6.2.0",
+ "lodash.get": "^4.4.2"
+ },
+ "bin": {
+ "json2csv": "bin/json2csv.js"
+ },
+ "engines": {
+ "node": ">= 12",
+ "npm": ">= 6.13.0"
+ }
+ },
+ "node_modules/json2csv/node_modules/commander": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
+ "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/jsonwebtoken": {
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
"integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
+ "license": "MIT",
"dependencies": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
@@ -4956,14 +9105,34 @@
"node_modules/jsonwebtoken/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/jszip": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
+ "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
+ "license": "(MIT OR GPL-3.0-or-later)",
+ "dependencies": {
+ "lie": "~3.3.0",
+ "pako": "~1.0.2",
+ "readable-stream": "~2.3.6",
+ "setimmediate": "^1.0.5"
+ }
+ },
+ "node_modules/jszip/node_modules/pako": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
+ "license": "(MIT AND Zlib)"
},
"node_modules/jwa": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
- "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz",
+ "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==",
+ "license": "MIT",
"dependencies": {
- "buffer-equal-constant-time": "1.0.1",
+ "buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
@@ -4972,6 +9141,7 @@
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+ "license": "MIT",
"dependencies": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
@@ -4982,23 +9152,58 @@
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"json-buffer": "3.0.1"
}
},
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/lazy": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz",
"integrity": "sha512-Y+CjUfLmIpoUCCRl0ub4smrYtGGr5AOa2AKOaWelGHOGz33X/Y/KizefGqbkwfz44+cnq/+9habclf8vOmu2LA==",
+ "license": "MIT",
"engines": {
"node": ">=0.2.0"
}
},
+ "node_modules/lazystream": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
+ "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
+ "license": "MIT",
+ "dependencies": {
+ "readable-stream": "^2.0.5"
+ },
+ "engines": {
+ "node": ">= 0.6.3"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"prelude-ls": "^1.2.1",
"type-check": "~0.4.0"
@@ -5007,11 +9212,34 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/lie": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
+ "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
+ "license": "MIT",
+ "dependencies": {
+ "immediate": "~3.0.5"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/listenercount": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz",
+ "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==",
+ "license": "ISC"
+ },
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"p-locate": "^5.0.0"
},
@@ -5025,75 +9253,155 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "license": "MIT"
},
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
- "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.defaults": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+ "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.difference": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
+ "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.escaperegexp": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz",
+ "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.flatten": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+ "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==",
+ "license": "MIT"
},
"node_modules/lodash.get": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
"integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
- "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead."
+ "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.",
+ "license": "MIT"
+ },
+ "node_modules/lodash.groupby": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz",
+ "integrity": "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==",
+ "license": "MIT"
},
"node_modules/lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
- "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
+ "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
+ "license": "MIT"
},
"node_modules/lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
- "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
+ "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
+ "license": "MIT"
},
"node_modules/lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
- "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead."
+ "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isfunction": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
+ "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==",
+ "license": "MIT"
},
"node_modules/lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
- "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
+ "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isnil": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz",
+ "integrity": "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==",
+ "license": "MIT"
},
"node_modules/lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
- "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
+ "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
+ "license": "MIT"
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
- "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+ "license": "MIT"
},
"node_modules/lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
- "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isundefined": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz",
+ "integrity": "sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==",
+ "license": "MIT"
},
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/lodash.mergewith": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
- "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ=="
+ "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
+ "license": "MIT"
},
"node_modules/lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
- "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
+ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.union": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
+ "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.uniq": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
+ "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
+ "license": "MIT"
+ },
+ "node_modules/long": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
+ "license": "Apache-2.0"
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "license": "MIT",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
@@ -5105,6 +9413,7 @@
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz",
"integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==",
+ "license": "MIT",
"dependencies": {
"fault": "^1.0.0",
"highlight.js": "~10.7.0"
@@ -5115,17 +9424,61 @@
}
},
"node_modules/lru-cache": {
- "version": "7.18.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
- "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/lru.min": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz",
+ "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==",
+ "license": "MIT",
"engines": {
- "node": ">=12"
+ "bun": ">=1.0.0",
+ "deno": ">=1.30.0",
+ "node": ">=8.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wellwelwel"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tmpl": "1.0.5"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
}
@@ -5134,6 +9487,7 @@
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -5142,22 +9496,46 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
"integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
+ "license": "MIT",
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
"node_modules/mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "license": "MIT",
"bin": {
"mime": "cli.js"
},
@@ -5169,6 +9547,7 @@
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -5177,6 +9556,7 @@
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
@@ -5184,10 +9564,21 @@
"node": ">= 0.6"
}
},
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/minim": {
"version": "0.23.8",
"resolved": "https://registry.npmjs.org/minim/-/minim-0.23.8.tgz",
"integrity": "sha512-bjdr2xW1dBCMsMGGsUeqM4eFI60m94+szhxWys+B1ztIt6gWSfeGBdSVCIawezeHYLYn0j6zrsXdQS/JllBzww==",
+ "license": "MIT",
"dependencies": {
"lodash": "^4.15.0"
},
@@ -5199,6 +9590,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -5210,43 +9602,55 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.6"
+ },
"bin": {
"mkdirp": "bin/cmd.js"
- },
- "engines": {
- "node": ">=10"
}
},
"node_modules/mnemonist": {
"version": "0.38.3",
"resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz",
"integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==",
+ "license": "MIT",
"dependencies": {
"obliterator": "^1.6.1"
}
},
+ "node_modules/module-alias": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.3.tgz",
+ "integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==",
+ "license": "MIT"
+ },
"node_modules/module-details-from-path": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz",
- "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A=="
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz",
+ "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==",
+ "license": "MIT"
},
"node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
},
"node_modules/multer": {
- "version": "1.4.5-lts.1",
- "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz",
- "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==",
+ "version": "1.4.5-lts.2",
+ "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.2.tgz",
+ "integrity": "sha512-VzGiVigcG9zUAoCNU+xShztrlr1auZOlurXynNvO9GiWD1/mTBbUljOKY+qMeazBqXgRnjzeEgJI/wyjJUHg9A==",
+ "license": "MIT",
"dependencies": {
"append-field": "^1.0.0",
"busboy": "^1.0.0",
@@ -5264,6 +9668,7 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/multer-s3/-/multer-s3-3.0.1.tgz",
"integrity": "sha512-BFwSO80a5EW4GJRBdUuSHblz2jhVSAze33ZbnGpcfEicoT0iRolx4kWR+AJV07THFRCQ78g+kelKFdjkCCaXeQ==",
+ "license": "MIT",
"dependencies": {
"@aws-sdk/lib-storage": "^3.46.0",
"file-type": "^3.3.0",
@@ -5277,32 +9682,77 @@
"@aws-sdk/client-s3": "^3.0.0"
}
},
- "node_modules/multer/node_modules/mkdirp": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
- "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "node_modules/mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+ "license": "ISC"
+ },
+ "node_modules/mysql2": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.1.tgz",
+ "integrity": "sha512-7ytuPQJjQB8TNAYX/H2yhL+iQOnIBjAMam361R7UAL0lOVXWjtdrmoL9HYKqKoLp/8UUTRcvo1QPvK9KL7wA8w==",
+ "license": "MIT",
"dependencies": {
- "minimist": "^1.2.6"
+ "aws-ssl-profiles": "^1.1.1",
+ "denque": "^2.1.0",
+ "generate-function": "^2.3.1",
+ "iconv-lite": "^0.6.3",
+ "long": "^5.2.1",
+ "lru.min": "^1.0.0",
+ "named-placeholders": "^1.1.3",
+ "seq-queue": "^0.0.5",
+ "sqlstring": "^2.3.2"
},
- "bin": {
- "mkdirp": "bin/cmd.js"
+ "engines": {
+ "node": ">= 8.0"
}
},
- "node_modules/mute-stream": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
- "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
+ "node_modules/mysql2/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/named-placeholders": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
+ "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
+ "license": "MIT",
+ "dependencies": {
+ "lru-cache": "^7.14.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/named-placeholders/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
},
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/needle": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz",
"integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==",
+ "license": "MIT",
"dependencies": {
"debug": "^3.2.6",
"iconv-lite": "^0.4.4",
@@ -5319,6 +9769,7 @@
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.1"
}
@@ -5326,12 +9777,20 @@
"node_modules/needle/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/needle/node_modules/sax": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
+ "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
+ "license": "ISC"
},
"node_modules/negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -5340,6 +9799,7 @@
"version": "0.6.18",
"resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz",
"integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==",
+ "license": "MIT",
"engines": {
"node": ">= 10"
}
@@ -5348,6 +9808,7 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
"integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.4.0"
}
@@ -5355,21 +9816,45 @@
"node_modules/node-abort-controller": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz",
- "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ=="
+ "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==",
+ "license": "MIT"
},
"node_modules/node-addon-api": {
"version": "8.3.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.1.tgz",
"integrity": "sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA==",
+ "license": "MIT",
"optional": true,
"engines": {
"node": "^18 || ^20 || >= 21"
}
},
+ "node_modules/node-cron": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.3.tgz",
+ "integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==",
+ "license": "ISC",
+ "dependencies": {
+ "uuid": "8.3.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/node-cron/node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
"node_modules/node-domexception": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+ "deprecated": "Use your platform's native DOMException instead",
"funding": [
{
"type": "github",
@@ -5380,6 +9865,7 @@
"url": "https://paypal.me/jimmywarting"
}
],
+ "license": "MIT",
"engines": {
"node": ">=10.5.0"
}
@@ -5388,6 +9874,7 @@
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/node-fetch-commonjs/-/node-fetch-commonjs-3.3.2.tgz",
"integrity": "sha512-VBlAiynj3VMLrotgwOS3OyECFxas5y7ltLcK4t41lMUZeaK15Ym4QRkqN0EQKAFL42q9i21EPKjzLUPfltR72A==",
+ "license": "MIT",
"dependencies": {
"node-domexception": "^1.0.0",
"web-streams-polyfill": "^3.0.3"
@@ -5404,6 +9891,7 @@
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
+ "license": "MIT",
"optional": true,
"bin": {
"node-gyp-build": "bin.js",
@@ -5411,18 +9899,119 @@
"node-gyp-build-test": "build-test.js"
}
},
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.19",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
+ "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nodemon": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz",
+ "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==",
+ "license": "MIT",
+ "dependencies": {
+ "chokidar": "^3.5.2",
+ "debug": "^4",
+ "ignore-by-default": "^1.0.1",
+ "minimatch": "^3.1.2",
+ "pstree.remy": "^1.1.8",
+ "semver": "^7.5.3",
+ "simple-update-notifier": "^2.0.0",
+ "supports-color": "^5.5.0",
+ "touch": "^3.1.0",
+ "undefsafe": "^2.0.5"
+ },
+ "bin": {
+ "nodemon": "bin/nodemon.js"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/nodemon"
+ }
+ },
+ "node_modules/nodemon/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/nodemon/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/nodemon/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/nodemon/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/nssocket": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/nssocket/-/nssocket-0.6.0.tgz",
"integrity": "sha512-a9GSOIql5IqgWJR3F/JXG4KpJTA3Z53Cj0MeMvGpglytB1nxE4PdFNC0jINe27CS7cGivoynwc054EzCcT3M3w==",
+ "license": "MIT",
"dependencies": {
"eventemitter2": "~0.4.14",
"lazy": "~1.0.11"
@@ -5434,12 +10023,14 @@
"node_modules/nssocket/node_modules/eventemitter2": {
"version": "0.4.14",
"resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz",
- "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ=="
+ "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==",
+ "license": "MIT"
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -5448,6 +10039,7 @@
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -5458,12 +10050,14 @@
"node_modules/obliterator": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz",
- "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig=="
+ "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==",
+ "license": "MIT"
},
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "license": "MIT",
"dependencies": {
"ee-first": "1.1.1"
},
@@ -5475,14 +10069,32 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/openapi-path-templating": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/openapi-path-templating/-/openapi-path-templating-2.1.1.tgz",
- "integrity": "sha512-nv9S9865cmJWY1E+MkUUSdxscVrsqqehYh7tRpkfj+0+HUI+w390c+DUBK1cS9n2d9TypzWPmhsBHFcqc1lp9w==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/openapi-path-templating/-/openapi-path-templating-2.2.1.tgz",
+ "integrity": "sha512-eN14VrDvl/YyGxxrkGOHkVkWEoPyhyeydOUrbvjoz8K5eIGgELASwN1eqFOJ2CTQMGCy2EntOK1KdtJ8ZMekcg==",
+ "license": "Apache-2.0",
"dependencies": {
"apg-lite": "^1.0.4"
},
@@ -5494,6 +10106,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/openapi-server-url-templating/-/openapi-server-url-templating-1.3.0.tgz",
"integrity": "sha512-DPlCms3KKEbjVQb0spV6Awfn6UWNheuG/+folQPzh/wUaKwuqvj8zt5gagD7qoyxtE03cIiKPgLFS3Q8Bz00uQ==",
+ "license": "Apache-2.0",
"dependencies": {
"apg-lite": "^1.0.4"
},
@@ -5505,6 +10118,7 @@
"version": "12.1.3",
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
"integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==",
+ "license": "MIT",
"peer": true
},
"node_modules/optionator": {
@@ -5512,6 +10126,7 @@
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"deep-is": "^0.1.3",
"fast-levenshtein": "^2.0.6",
@@ -5529,6 +10144,7 @@
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"yocto-queue": "^0.1.0"
},
@@ -5544,6 +10160,7 @@
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"p-limit": "^3.0.2"
},
@@ -5554,10 +10171,20 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/pac-proxy-agent": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz",
"integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==",
+ "license": "MIT",
"dependencies": {
"@tootallnate/quickjs-emscripten": "^0.23.0",
"agent-base": "^7.1.2",
@@ -5573,9 +10200,10 @@
}
},
"node_modules/pac-proxy-agent/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
@@ -5591,12 +10219,14 @@
"node_modules/pac-proxy-agent/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
},
"node_modules/pac-resolver": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
"integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
+ "license": "MIT",
"dependencies": {
"degenerator": "^5.0.0",
"netmask": "^2.0.2"
@@ -5608,13 +10238,15 @@
"node_modules/pako": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
- "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA=="
+ "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==",
+ "license": "MIT"
},
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"callsites": "^3.0.0"
},
@@ -5626,6 +10258,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
"integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
+ "license": "MIT",
"dependencies": {
"character-entities": "^1.0.0",
"character-entities-legacy": "^1.0.0",
@@ -5635,14 +10268,51 @@
"is-hexadecimal": "^1.0.0"
},
"funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/parse-imports-exports": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/parse-imports-exports/-/parse-imports-exports-0.2.4.tgz",
+ "integrity": "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parse-statements": "1.0.11"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/parse-statements": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/parse-statements/-/parse-statements-1.0.11.tgz",
+ "integrity": "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -5651,7 +10321,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -5660,6 +10330,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -5669,6 +10340,7 @@
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -5676,17 +10348,27 @@
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "license": "MIT"
},
"node_modules/path-to-regexp": {
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
- "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="
+ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "license": "MIT",
"engines": {
"node": ">=8.6"
},
@@ -5698,6 +10380,7 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/pidusage/-/pidusage-3.0.2.tgz",
"integrity": "sha512-g0VU+y08pKw5M8EZ2rIGiEBaB8wrQMjYGFfW2QVIfyT8V+fq8YFLkvlz4bz5ljvFDJYNFCWT3PWqcRr2FKO81w==",
+ "license": "MIT",
"dependencies": {
"safe-buffer": "^5.2.1"
},
@@ -5705,10 +10388,100 @@
"node": ">=10"
}
},
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkce-challenge": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz",
+ "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/pm2": {
"version": "5.4.3",
"resolved": "https://registry.npmjs.org/pm2/-/pm2-5.4.3.tgz",
"integrity": "sha512-4/I1htIHzZk1Y67UgOCo4F1cJtas1kSds31N8zN0PybO230id1nigyjGuGFzUnGmUFPmrJ0On22fO1ChFlp7VQ==",
+ "license": "AGPL-3.0",
"dependencies": {
"@pm2/agent": "~2.0.0",
"@pm2/io": "~6.0.1",
@@ -5757,6 +10530,7 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pm2-axon/-/pm2-axon-4.0.1.tgz",
"integrity": "sha512-kES/PeSLS8orT8dR5jMlNl+Yu4Ty3nbvZRmaAtROuVm9nYYGiaoXqqKQqQYzWQzMYWUKHMQTvBlirjE5GIIxqg==",
+ "license": "MIT",
"dependencies": {
"amp": "~0.3.1",
"amp-message": "~0.1.1",
@@ -5771,6 +10545,7 @@
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/pm2-axon-rpc/-/pm2-axon-rpc-0.7.1.tgz",
"integrity": "sha512-FbLvW60w+vEyvMjP/xom2UPhUN/2bVpdtLfKJeYM3gwzYhoTEEChCOICfFzxkxuoEleOlnpjie+n1nue91bDQw==",
+ "license": "MIT",
"dependencies": {
"debug": "^4.3.1"
},
@@ -5779,9 +10554,10 @@
}
},
"node_modules/pm2-axon-rpc/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
@@ -5797,12 +10573,14 @@
"node_modules/pm2-axon-rpc/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
},
"node_modules/pm2-axon/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
@@ -5818,12 +10596,14 @@
"node_modules/pm2-axon/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
},
"node_modules/pm2-deploy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pm2-deploy/-/pm2-deploy-1.0.2.tgz",
"integrity": "sha512-YJx6RXKrVrWaphEYf++EdOOx9EH18vM8RSZN/P1Y+NokTKqYAca/ejXwVLyiEpNju4HPZEk3Y2uZouwMqUlcgg==",
+ "license": "MIT",
"dependencies": {
"run-series": "^1.1.8",
"tv4": "^1.3.0"
@@ -5836,6 +10616,7 @@
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/pm2-multimeter/-/pm2-multimeter-0.1.2.tgz",
"integrity": "sha512-S+wT6XfyKfd7SJIBqRgOctGxaBzUOmVQzTAS+cg04TsEUObJVreha7lvCfX8zzGVr871XwCSnHUU7DQQ5xEsfA==",
+ "license": "MIT/X11",
"dependencies": {
"charm": "~0.1.1"
}
@@ -5844,6 +10625,7 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/pm2-sysmonit/-/pm2-sysmonit-1.2.8.tgz",
"integrity": "sha512-ACOhlONEXdCTVwKieBIQLSi2tQZ8eKinhcr9JpZSUAL8Qy0ajIgRtsLxG/lwPOW3JEKqPyw/UaHmTWhUzpP4kA==",
+ "license": "Apache",
"optional": true,
"dependencies": {
"async": "^3.2.0",
@@ -5854,9 +10636,10 @@
}
},
"node_modules/pm2-sysmonit/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
"optional": true,
"dependencies": {
"ms": "^2.1.3"
@@ -5874,12 +10657,14 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT",
"optional": true
},
"node_modules/pm2-sysmonit/node_modules/pidusage": {
"version": "2.0.21",
"resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.21.tgz",
"integrity": "sha512-cv3xAQos+pugVX+BfXpHsbyz/dLzX+lr44zNMsYiGxUw+kV5sgQCIcLd1z+0vq+KyC7dJ+/ts2PsfgWfSC3WXA==",
+ "license": "MIT",
"optional": true,
"dependencies": {
"safe-buffer": "^5.2.1"
@@ -5888,10 +10673,24 @@
"node": ">=8"
}
},
+ "node_modules/pm2/node_modules/chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/pm2/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
@@ -5904,15 +10703,48 @@
}
}
},
+ "node_modules/pm2/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/pm2/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/pm2/node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/pngjs": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
+ "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ }
},
"node_modules/possible-typed-array-names": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
"integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
}
@@ -5922,14 +10754,44 @@
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.8.0"
}
},
+ "node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
"node_modules/prismjs": {
- "version": "1.29.0",
- "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",
- "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==",
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
+ "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
+ "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -5938,6 +10800,7 @@
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6.0"
}
@@ -5945,30 +10808,54 @@
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "license": "MIT"
},
"node_modules/promptly": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/promptly/-/promptly-2.2.0.tgz",
"integrity": "sha512-aC9j+BZsRSSzEsXBNBwDnAxujdx19HycZoKgRgzWnS8eOHg1asuf9heuLprfbe739zY3IdUQx+Egv6Jn135WHA==",
+ "license": "MIT",
"dependencies": {
"read": "^1.0.4"
}
},
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "license": "MIT",
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
"react-is": "^16.13.1"
}
},
+ "node_modules/prop-types/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "license": "MIT"
+ },
"node_modules/property-information": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz",
"integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==",
+ "license": "MIT",
"dependencies": {
"xtend": "^4.0.0"
},
@@ -5981,6 +10868,7 @@
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "license": "MIT",
"dependencies": {
"forwarded": "0.2.0",
"ipaddr.js": "1.9.1"
@@ -5993,6 +10881,7 @@
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz",
"integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==",
+ "license": "MIT",
"dependencies": {
"agent-base": "^7.0.2",
"debug": "^4.3.4",
@@ -6008,9 +10897,10 @@
}
},
"node_modules/proxy-agent/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
@@ -6023,25 +10913,200 @@
}
}
},
+ "node_modules/proxy-agent/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/proxy-agent/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
+ "node_modules/pstree.remy": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
+ "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
+ "license": "MIT"
},
"node_modules/punycode": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
- "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pure-rand": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
+ "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/qrcode": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz",
+ "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
+ "license": "MIT",
+ "dependencies": {
+ "dijkstrajs": "^1.0.1",
+ "pngjs": "^5.0.0",
+ "yargs": "^15.3.1"
+ },
+ "bin": {
+ "qrcode": "bin/qrcode"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/qrcode/node_modules/cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "node_modules/qrcode/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/qrcode/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/y18n": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+ "license": "ISC"
+ },
+ "node_modules/qrcode/node_modules/yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
},
"node_modules/qs": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
+ "license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.0.6"
},
@@ -6064,7 +11129,8 @@
"node_modules/querystringify": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
- "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+ "license": "MIT"
},
"node_modules/queue-microtask": {
"version": "1.2.3",
@@ -6083,12 +11149,14 @@
"type": "consulting",
"url": "https://feross.org/support"
}
- ]
+ ],
+ "license": "MIT"
},
"node_modules/ramda": {
"version": "0.30.1",
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.30.1.tgz",
"integrity": "sha512-tEF5I22zJnuclswcZMc8bDIrwRHRzf+NqVEmqg50ShAZMP7MWeR/RGDthfM/p+BlqvF2fXAzpn8i+SJcYD3alw==",
+ "license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/ramda"
@@ -6098,6 +11166,7 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ramda-adjunct/-/ramda-adjunct-5.1.0.tgz",
"integrity": "sha512-8qCpl2vZBXEJyNbi4zqcgdfHtcdsWjOGbiNSEnEBrM6Y0OKOT8UxJbIVGm1TIcjaSu2MxaWcgtsNlKlCk7o7qg==",
+ "license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.3"
},
@@ -6113,6 +11182,7 @@
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/randexp/-/randexp-0.5.3.tgz",
"integrity": "sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==",
+ "license": "MIT",
"dependencies": {
"drange": "^1.0.2",
"ret": "^0.2.0"
@@ -6121,10 +11191,19 @@
"node": ">=4"
}
},
+ "node_modules/random-bytes": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
+ "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "license": "MIT",
"dependencies": {
"safe-buffer": "^5.1.0"
}
@@ -6133,6 +11212,7 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -6141,6 +11221,7 @@
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
+ "license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
@@ -6155,6 +11236,7 @@
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -6166,6 +11248,7 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz",
"integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==",
+ "license": "MIT",
"dependencies": {
"copy-to-clipboard": "^3.3.1",
"prop-types": "^15.8.1"
@@ -6178,6 +11261,7 @@
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/react-debounce-input/-/react-debounce-input-3.3.0.tgz",
"integrity": "sha512-VEqkvs8JvY/IIZvh71Z0TC+mdbxERvYF33RcebnodlsUZ8RSgyKe2VWaHXv4+/8aoOgXLxWrdsYs2hDhcwbUgA==",
+ "license": "MIT",
"dependencies": {
"lodash.debounce": "^4",
"prop-types": "^15.8.1"
@@ -6190,6 +11274,7 @@
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@@ -6202,6 +11287,7 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/react-immutable-proptypes/-/react-immutable-proptypes-2.2.0.tgz",
"integrity": "sha512-Vf4gBsePlwdGvSZoLSBfd4HAP93HDauMY4fDjXhreg/vg6F3Fj/MXDNyTbltPC/xZKmZc+cjLu3598DdYK6sgQ==",
+ "license": "MIT",
"dependencies": {
"invariant": "^2.2.2"
},
@@ -6213,6 +11299,7 @@
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/react-immutable-pure-component/-/react-immutable-pure-component-2.2.2.tgz",
"integrity": "sha512-vkgoMJUDqHZfXXnjVlG3keCxSO/U6WeDQ5/Sl0GK2cH8TOxEzQ5jXqDXHEL/jqk6fsNxV05oH5kD7VNMUE2k+A==",
+ "license": "MIT",
"peerDependencies": {
"immutable": ">= 2 || >= 4.0.0-rc",
"react": ">= 16.6",
@@ -6223,19 +11310,23 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-6.0.2.tgz",
"integrity": "sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ==",
+ "license": "MIT",
"peerDependencies": {
"react": "^16.8.4 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/react-redux": {
"version": "9.2.0",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
"integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
+ "license": "MIT",
"dependencies": {
"@types/use-sync-external-store": "^0.0.6",
"use-sync-external-store": "^1.4.0"
@@ -6258,6 +11349,7 @@
"version": "15.6.1",
"resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.1.tgz",
"integrity": "sha512-OqJ2/vL7lEeV5zTJyG7kmARppUjiB9h9udl4qHQjjgEos66z00Ia0OckwYfRxCSFrW8RJIBnsBwQsHZbVPspqg==",
+ "license": "MIT",
"dependencies": {
"@babel/runtime": "^7.3.1",
"highlight.js": "^10.4.1",
@@ -6274,6 +11366,7 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
"integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==",
+ "license": "ISC",
"dependencies": {
"mute-stream": "~0.0.4"
},
@@ -6285,6 +11378,7 @@
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "license": "MIT",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@@ -6295,15 +11389,47 @@
"util-deprecate": "~1.0.1"
}
},
- "node_modules/readable-stream/node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ "node_modules/readable-stream/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "license": "MIT"
+ },
+ "node_modules/readdir-glob": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz",
+ "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "minimatch": "^5.1.0"
+ }
+ },
+ "node_modules/readdir-glob/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/readdir-glob/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
},
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "license": "MIT",
"dependencies": {
"picomatch": "^2.2.1"
},
@@ -6311,15 +11437,32 @@
"node": ">=8.10.0"
}
},
+ "node_modules/redis": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/redis/-/redis-5.1.0.tgz",
+ "integrity": "sha512-5G5k9sYo5H5L0kd7UETiJZFTkIClH31fSmaEk2eU8E7mrmF0J1t6RqmFXOCJmSRlNd3QyvDUK/AWL9psbKaN0Q==",
+ "dependencies": {
+ "@redis/bloom": "5.1.0",
+ "@redis/client": "5.1.0",
+ "@redis/json": "5.1.0",
+ "@redis/search": "5.1.0",
+ "@redis/time-series": "5.1.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
"node_modules/redux": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
- "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="
+ "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
+ "license": "MIT"
},
"node_modules/redux-immutable": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/redux-immutable/-/redux-immutable-4.0.0.tgz",
"integrity": "sha512-SchSn/DWfGb3oAejd+1hhHx01xUoxY+V7TeK0BKqpkLKiQPVFf7DYzEaKmrEVxsWxielKfSK9/Xq66YyxgR1cg==",
+ "license": "BSD-3-Clause",
"peerDependencies": {
"immutable": "^3.8.1 || ^4.0.0-rc.1"
}
@@ -6328,6 +11471,7 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz",
"integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==",
+ "license": "MIT",
"dependencies": {
"hastscript": "^6.0.0",
"parse-entities": "^2.0.0",
@@ -6342,19 +11486,16 @@
"version": "1.27.0",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz",
"integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==",
+ "license": "MIT",
"engines": {
"node": ">=6"
}
},
- "node_modules/regenerator-runtime": {
- "version": "0.14.1",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
- "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
- },
"node_modules/remarkable": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/remarkable/-/remarkable-2.0.1.tgz",
"integrity": "sha512-YJyMcOH5lrR+kZdmB0aJJ4+93bEojRZ1HGDn9Eagu6ibg7aVZhc3OWbbShRid+Q5eAfsEqWxpe+g5W5nYNfNiA==",
+ "license": "MIT",
"dependencies": {
"argparse": "^1.0.10",
"autolinker": "^3.11.0"
@@ -6370,6 +11511,7 @@
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "license": "MIT",
"dependencies": {
"sprintf-js": "~1.0.2"
}
@@ -6377,20 +11519,32 @@
"node_modules/remarkable/node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "license": "BSD-3-Clause"
},
"node_modules/repeat-string": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
"integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
+ "license": "MIT",
"engines": {
"node": ">=0.10"
}
},
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/require-in-the-middle": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.2.0.tgz",
"integrity": "sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg==",
+ "license": "MIT",
"dependencies": {
"debug": "^4.1.1",
"module-details-from-path": "^1.0.3",
@@ -6401,9 +11555,10 @@
}
},
"node_modules/require-in-the-middle/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
@@ -6419,22 +11574,32 @@
"node_modules/require-in-the-middle/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "license": "ISC"
},
"node_modules/requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
- "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "license": "MIT"
},
"node_modules/reselect": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
- "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w=="
+ "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==",
+ "license": "MIT"
},
"node_modules/resolve": {
"version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
"integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
+ "license": "MIT",
"dependencies": {
"is-core-module": "^2.16.0",
"path-parse": "^1.0.7",
@@ -6450,23 +11615,128 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-cwd/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=4"
}
},
+ "node_modules/resolve.exports": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz",
+ "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/ret": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz",
"integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==",
+ "license": "MIT",
"engines": {
"node": ">=4"
}
},
+ "node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/rndm": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz",
+ "integrity": "sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw=="
+ },
+ "node_modules/router": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
+ "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "is-promise": "^4.0.0",
+ "parseurl": "^1.3.3",
+ "path-to-regexp": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/router/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/router/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/router/node_modules/path-to-regexp": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
+ "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ }
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -6485,6 +11755,7 @@
"url": "https://feross.org/support"
}
],
+ "license": "MIT",
"dependencies": {
"queue-microtask": "^1.2.2"
}
@@ -6506,7 +11777,8 @@
"type": "consulting",
"url": "https://feross.org/support"
}
- ]
+ ],
+ "license": "MIT"
},
"node_modules/safe-buffer": {
"version": "5.2.1",
@@ -6525,12 +11797,14 @@
"type": "consulting",
"url": "https://feross.org/support"
}
- ]
+ ],
+ "license": "MIT"
},
"node_modules/safe-regex-test": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
"integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
@@ -6546,25 +11820,41 @@
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
},
"node_modules/sax": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
- "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
+ "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==",
+ "license": "ISC"
+ },
+ "node_modules/saxes": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
+ "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==",
+ "license": "ISC",
+ "dependencies": {
+ "xmlchars": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
},
"node_modules/scheduler": {
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
}
},
"node_modules/semver": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
- "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
@@ -6576,6 +11866,7 @@
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
+ "license": "MIT",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
@@ -6599,6 +11890,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -6606,12 +11898,19 @@
"node_modules/send/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/seq-queue": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
+ "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
},
"node_modules/serialize-error": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz",
"integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==",
+ "license": "MIT",
"dependencies": {
"type-fest": "^0.20.2"
},
@@ -6622,10 +11921,23 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/serialize-error/node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/serve-static": {
"version": "1.16.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
"integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
+ "license": "MIT",
"dependencies": {
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
@@ -6636,10 +11948,17 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+ "license": "ISC"
+ },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "license": "MIT",
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
@@ -6652,15 +11971,23 @@
"node": ">= 0.4"
}
},
+ "node_modules/setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
+ "license": "MIT"
+ },
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC"
},
"node_modules/sha.js": {
"version": "2.4.11",
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+ "license": "(MIT AND BSD-3-Clause)",
"dependencies": {
"inherits": "^2.0.1",
"safe-buffer": "^5.0.1"
@@ -6674,6 +12001,7 @@
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"shebang-regex": "^3.0.0"
},
@@ -6686,6 +12014,7 @@
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -6693,12 +12022,14 @@
"node_modules/shimmer": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz",
- "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="
+ "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==",
+ "license": "BSD-2-Clause"
},
"node_modules/short-unique-id": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-5.2.0.tgz",
- "integrity": "sha512-cMGfwNyfDZ/nzJ2k2M+ClthBIh//GlZl1JEf47Uoa9XR11bz8Pa2T2wQO4bVrRdH48LrIDWJahQziKo3MjhsWg==",
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-5.3.2.tgz",
+ "integrity": "sha512-KRT/hufMSxXKEDSQujfVE0Faa/kZ51ihUcZQAcmP04t00DvPj7Ox5anHke1sJYUtzSuiT/Y5uyzg/W7bBEGhCg==",
+ "license": "Apache-2.0",
"bin": {
"short-unique-id": "bin/short-unique-id",
"suid": "bin/short-unique-id"
@@ -6708,6 +12039,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3",
@@ -6726,6 +12058,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+ "license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3"
@@ -6741,6 +12074,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
@@ -6758,6 +12092,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
@@ -6775,12 +12110,43 @@
"node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "license": "ISC"
+ },
+ "node_modules/simple-update-notifier": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
+ "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
},
"node_modules/smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "license": "MIT",
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
@@ -6790,6 +12156,7 @@
"version": "2.8.4",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz",
"integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==",
+ "license": "MIT",
"dependencies": {
"ip-address": "^9.0.5",
"smart-buffer": "^4.2.0"
@@ -6803,6 +12170,7 @@
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz",
"integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==",
+ "license": "MIT",
"dependencies": {
"agent-base": "^7.1.2",
"debug": "^4.3.4",
@@ -6813,9 +12181,10 @@
}
},
"node_modules/socks-proxy-agent/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
@@ -6831,20 +12200,24 @@
"node_modules/socks-proxy-agent/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
- "version": "0.5.21",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
- "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
@@ -6854,20 +12227,92 @@
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz",
"integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==",
+ "license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/spdx-exceptions": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
+ "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
+ "dev": true,
+ "license": "CC-BY-3.0"
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz",
+ "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.21",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz",
+ "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/speakeasy": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/speakeasy/-/speakeasy-2.0.0.tgz",
+ "integrity": "sha512-lW2A2s5LKi8rwu77ewisuUOtlCydF/hmQSOJjpTqTj1gZLkNgTaYnyvfxy2WBr4T/h+9c4g8HIITfj83OkFQFw==",
+ "license": "MIT",
+ "dependencies": {
+ "base32.js": "0.0.1"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
"node_modules/sprintf-js": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
- "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
+ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/sqlstring": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
+ "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/stack-utils": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
+ "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/stack-utils/node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
},
"node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -6876,6 +12321,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz",
"integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==",
+ "license": "MIT",
"dependencies": {
"inherits": "~2.0.4",
"readable-stream": "^3.5.0"
@@ -6885,6 +12331,7 @@
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
@@ -6906,42 +12353,175 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "license": "MIT",
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
- "node_modules/string_decoder/node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
- },
- "node_modules/strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true,
- "engines": {
- "node": ">=8"
+ "node_modules/string_decoder/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "license": "MIT"
+ },
+ "node_modules/string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strnum": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz",
+ "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/superagent": {
+ "version": "10.2.1",
+ "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.2.1.tgz",
+ "integrity": "sha512-O+PCv11lgTNJUzy49teNAWLjBZfc+A1enOwTpLlH6/rsvKcTwcdTT8m9azGkVqM7HBl5jpyZ7KTPhHweokBcdg==",
+ "license": "MIT",
+ "dependencies": {
+ "component-emitter": "^1.3.0",
+ "cookiejar": "^2.1.4",
+ "debug": "^4.3.4",
+ "fast-safe-stringify": "^2.1.1",
+ "form-data": "^4.0.0",
+ "formidable": "^3.5.4",
+ "methods": "^1.1.2",
+ "mime": "2.6.0",
+ "qs": "^6.11.0"
+ },
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "node_modules/superagent/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/superagent/node_modules/mime": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "engines": {
+ "node": ">=4.0.0"
}
},
- "node_modules/strnum": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz",
- "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/NaturalIntelligence"
- }
- ]
+ "node_modules/superagent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/supertest": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.1.tgz",
+ "integrity": "sha512-aI59HBTlG9e2wTjxGJV+DygfNLgnWbGdZxiA/sgrnNNikIW8lbDvCtF6RnhZoJ82nU7qv7ZLjrvWqCEm52fAmw==",
+ "license": "MIT",
+ "dependencies": {
+ "methods": "^1.1.2",
+ "superagent": "^10.2.1"
+ },
+ "engines": {
+ "node": ">=14.18.0"
+ }
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -6953,6 +12533,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -6961,17 +12542,18 @@
}
},
"node_modules/swagger-client": {
- "version": "3.34.1",
- "resolved": "https://registry.npmjs.org/swagger-client/-/swagger-client-3.34.1.tgz",
- "integrity": "sha512-aqk315C959936kijVpR28Q07eugElW9vp77a57hdFlQDF8Kuln7SeB1MwXnTCOQEM6/pIWYN00QlvIEwHqQkqw==",
+ "version": "3.35.3",
+ "resolved": "https://registry.npmjs.org/swagger-client/-/swagger-client-3.35.3.tgz",
+ "integrity": "sha512-4bO+dhBbasP485Ak67o46cWNVUnV0/92ypb2997bhvxTO2M+IuQZM1ilkN/7nSaiGuxDKJhkuL54I35PVI3AAw==",
+ "license": "Apache-2.0",
"dependencies": {
"@babel/runtime-corejs3": "^7.22.15",
"@scarf/scarf": "=1.4.0",
- "@swagger-api/apidom-core": ">=1.0.0-beta.12 <1.0.0-rc.0",
- "@swagger-api/apidom-error": ">=1.0.0-beta.12 <1.0.0-rc.0",
- "@swagger-api/apidom-json-pointer": ">=1.0.0-beta.12 <1.0.0-rc.0",
- "@swagger-api/apidom-ns-openapi-3-1": ">=1.0.0-beta.12 <1.0.0-rc.0",
- "@swagger-api/apidom-reference": ">=1.0.0-beta.12 <1.0.0-rc.0",
+ "@swagger-api/apidom-core": ">=1.0.0-beta.39 <1.0.0-rc.0",
+ "@swagger-api/apidom-error": ">=1.0.0-beta.39 <1.0.0-rc.0",
+ "@swagger-api/apidom-json-pointer": ">=1.0.0-beta.39 <1.0.0-rc.0",
+ "@swagger-api/apidom-ns-openapi-3-1": ">=1.0.0-beta.39 <1.0.0-rc.0",
+ "@swagger-api/apidom-reference": ">=1.0.0-beta.39 <1.0.0-rc.0",
"@swaggerexpert/cookie": "^2.0.2",
"deepmerge": "~4.3.0",
"fast-json-patch": "^3.0.0-1",
@@ -6979,16 +12561,17 @@
"neotraverse": "=0.6.18",
"node-abort-controller": "^3.1.1",
"node-fetch-commonjs": "^3.3.2",
- "openapi-path-templating": "^2.0.1",
- "openapi-server-url-templating": "^1.2.0",
+ "openapi-path-templating": "^2.2.1",
+ "openapi-server-url-templating": "^1.3.0",
"ramda": "^0.30.1",
- "ramda-adjunct": "^5.0.0"
+ "ramda-adjunct": "^5.1.0"
}
},
"node_modules/swagger-jsdoc": {
"version": "6.2.8",
"resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz",
"integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==",
+ "license": "MIT",
"dependencies": {
"commander": "6.2.0",
"doctrine": "3.0.0",
@@ -7008,14 +12591,37 @@
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz",
"integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==",
+ "license": "MIT",
"engines": {
"node": ">= 6"
}
},
+ "node_modules/swagger-jsdoc/node_modules/glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/swagger-parser": {
"version": "10.0.3",
"resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz",
"integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==",
+ "license": "MIT",
"dependencies": {
"@apidevtools/swagger-parser": "10.0.3"
},
@@ -7024,11 +12630,12 @@
}
},
"node_modules/swagger-ui": {
- "version": "5.20.0",
- "resolved": "https://registry.npmjs.org/swagger-ui/-/swagger-ui-5.20.0.tgz",
- "integrity": "sha512-sqRZGkODumnNr3Ienb+cKRowwYd/Q4b3j6gMLrBVtnQRIr92wT0O3TAH5S0x/v84jxHfibug/e0y4glSfbd0og==",
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/swagger-ui/-/swagger-ui-5.22.0.tgz",
+ "integrity": "sha512-xGc24TU6wgS5YWVcxwy90GUgqbHYvWvtvftjptfjXEMgetdvGWnI8CNRaYG3hG5bIl5Zt1rfai4NO2lBxAUswg==",
+ "license": "Apache-2.0",
"dependencies": {
- "@babel/runtime-corejs3": "^7.26.7",
+ "@babel/runtime-corejs3": "^7.27.1",
"@scarf/scarf": "=1.4.0",
"base64-js": "^1.5.1",
"classnames": "^2.5.1",
@@ -7058,7 +12665,7 @@
"reselect": "^5.1.1",
"serialize-error": "^8.1.0",
"sha.js": "^2.4.11",
- "swagger-client": "^3.34.1",
+ "swagger-client": "^3.35.3",
"url-parse": "^1.5.10",
"xml": "=1.0.1",
"xml-but-prettier": "^1.0.1",
@@ -7066,9 +12673,10 @@
}
},
"node_modules/swagger-ui-dist": {
- "version": "5.20.0",
- "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.20.0.tgz",
- "integrity": "sha512-V5pozVTZxivdoQq/SQWxj3A4cOu5opk9MEbcZANX3Pj8X8xCrD1QCtBT7744Pz9msOvt0nnmy9JvM/9PGonCdg==",
+ "version": "5.21.0",
+ "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.21.0.tgz",
+ "integrity": "sha512-E0K3AB6HvQd8yQNSMR7eE5bk+323AUxjtCz/4ZNKiahOlPhPJxqn3UPIGs00cyY/dhrTDJ61L7C/a8u6zhGrZg==",
+ "license": "Apache-2.0",
"dependencies": {
"@scarf/scarf": "=1.4.0"
}
@@ -7077,6 +12685,7 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz",
"integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==",
+ "license": "MIT",
"dependencies": {
"swagger-ui-dist": ">=5.0.0"
},
@@ -7104,12 +12713,14 @@
"type": "consulting",
"url": "https://feross.org/support"
}
- ]
+ ],
+ "license": "BSD-3-Clause"
},
"node_modules/systeminformation": {
"version": "5.25.11",
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.25.11.tgz",
"integrity": "sha512-jI01fn/t47rrLTQB0FTlMCC+5dYx8o0RRF+R4BPiUNsvg5OdY0s9DKMFmJGrx5SwMZQ4cag0Gl6v8oycso9b/g==",
+ "license": "MIT",
"optional": true,
"os": [
"darwin",
@@ -7132,10 +12743,72 @@
"url": "https://www.buymeacoffee.com/systeminfo"
}
},
+ "node_modules/tar-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tar-stream/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tmp": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
+ "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
@@ -7146,21 +12819,42 @@
"node_modules/toggle-selection": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
- "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
+ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==",
+ "license": "MIT"
},
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
"engines": {
"node": ">=0.6"
}
},
+ "node_modules/touch": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz",
+ "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==",
+ "license": "ISC",
+ "bin": {
+ "nodetouch": "bin/nodetouch.js"
+ }
+ },
+ "node_modules/traverse": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
+ "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==",
+ "license": "MIT/X11",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/tree-sitter": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.21.1.tgz",
"integrity": "sha512-7dxoA6kYvtgWw80265MyqJlkRl4yawIjO7S5MigytjELkX43fV2WsAXzsNfO7sBpPPCF5Gp0+XzHk0DwLCq3xQ==",
"hasInstallScript": true,
+ "license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
@@ -7173,6 +12867,7 @@
"resolved": "https://registry.npmjs.org/tree-sitter-json/-/tree-sitter-json-0.24.8.tgz",
"integrity": "sha512-Tc9ZZYwHyWZ3Tt1VEw7Pa2scu1YO7/d2BCBbKTx5hXwig3UfdQjsOPkPyLpDJOn/m1UBEWYAtSdGAwCSyagBqQ==",
"hasInstallScript": true,
+ "license": "MIT",
"optional": true,
"dependencies": {
"node-addon-api": "^8.2.2",
@@ -7190,22 +12885,43 @@
"node_modules/ts-mixer": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz",
- "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA=="
+ "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==",
+ "license": "MIT"
},
"node_modules/ts-toolbelt": {
"version": "9.6.0",
"resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz",
- "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w=="
+ "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==",
+ "license": "Apache-2.0"
},
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
- "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
+ "node_modules/tsscmp": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
+ "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==",
+ "engines": {
+ "node": ">=0.6.x"
+ }
},
"node_modules/tv4": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz",
"integrity": "sha512-afizzfpJgvPr+eDkREK4MxJ/+r8nEEHcmitwgnPUqpaP+FpwQyadnxNoSACbgc/b1LsZYtODGoPiFxQrgJgjvw==",
+ "license": [
+ {
+ "type": "Public Domain",
+ "url": "http://geraintluff.github.io/tv4/LICENSE.txt"
+ },
+ {
+ "type": "MIT",
+ "url": "http://jsonary.com/LICENSE.txt"
+ }
+ ],
"engines": {
"node": ">= 0.8.0"
}
@@ -7214,6 +12930,7 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tx2/-/tx2-1.0.5.tgz",
"integrity": "sha512-sJ24w0y03Md/bxzK4FU8J8JveYYUbSs2FViLJ2D/8bytSiyPRbuE3DyL/9UKYXTZlV3yXq0L8GLlhobTnekCVg==",
+ "license": "MIT",
"optional": true,
"dependencies": {
"json-stringify-safe": "^5.0.1"
@@ -7224,6 +12941,7 @@
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"prelude-ls": "^1.2.1"
},
@@ -7231,10 +12949,22 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
"engines": {
"node": ">=10"
},
@@ -7246,6 +12976,7 @@
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "license": "MIT",
"dependencies": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
@@ -7257,20 +12988,47 @@
"node_modules/typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
+ "license": "MIT"
},
"node_modules/types-ramda": {
"version": "0.30.1",
"resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.30.1.tgz",
"integrity": "sha512-1HTsf5/QVRmLzcGfldPFvkVsAdi1db1BBKzi7iW3KBUlOICg/nKnFS+jGqDJS3YD8VsWbAh7JiHeBvbsw8RPxA==",
+ "license": "MIT",
"dependencies": {
"ts-toolbelt": "^9.6.0"
}
},
+ "node_modules/uid-safe": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
+ "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
+ "dependencies": {
+ "random-bytes": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/undefsafe": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
+ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
+ "license": "MIT"
+ },
+ "node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -7278,30 +13036,73 @@
"node_modules/unraw": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/unraw/-/unraw-3.0.0.tgz",
- "integrity": "sha512-08/DA66UF65OlpUDIQtbJyrqTR0jTAlJ+jsnkQ4jxR7+K5g5YG1APZKQSMCE1vqqmD+2pv6+IdEjmopFatacvg=="
+ "integrity": "sha512-08/DA66UF65OlpUDIQtbJyrqTR0jTAlJ+jsnkQ4jxR7+K5g5YG1APZKQSMCE1vqqmD+2pv6+IdEjmopFatacvg==",
+ "license": "MIT"
+ },
+ "node_modules/unzipper": {
+ "version": "0.10.14",
+ "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz",
+ "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==",
+ "license": "MIT",
+ "dependencies": {
+ "big-integer": "^1.6.17",
+ "binary": "~0.3.0",
+ "bluebird": "~3.4.1",
+ "buffer-indexof-polyfill": "~1.0.0",
+ "duplexer2": "~0.1.4",
+ "fstream": "^1.0.12",
+ "graceful-fs": "^4.2.2",
+ "listenercount": "~1.0.1",
+ "readable-stream": "~2.3.6",
+ "setimmediate": "~1.0.4"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
+ "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
},
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"punycode": "^2.1.0"
}
},
- "node_modules/uri-js/node_modules/punycode": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
- "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/url": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz",
"integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==",
+ "license": "MIT",
"dependencies": {
"punycode": "1.3.2",
"querystring": "0.2.0"
@@ -7311,15 +13112,23 @@
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "license": "MIT",
"dependencies": {
"querystringify": "^2.1.1",
"requires-port": "^1.0.0"
}
},
+ "node_modules/url/node_modules/punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==",
+ "license": "MIT"
+ },
"node_modules/use-sync-external-store": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz",
- "integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
+ "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
+ "license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
@@ -7328,6 +13137,7 @@
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
"integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
+ "license": "MIT",
"dependencies": {
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
@@ -7339,12 +13149,14 @@
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
},
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "license": "MIT",
"engines": {
"node": ">= 0.4.0"
}
@@ -7357,14 +13169,31 @@
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
+ "license": "MIT",
"bin": {
"uuid": "dist/bin/uuid"
}
},
+ "node_modules/v8-to-istanbul": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
+ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
"node_modules/validator": {
- "version": "13.12.0",
- "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz",
- "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==",
+ "version": "13.15.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.0.tgz",
+ "integrity": "sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==",
+ "license": "MIT",
"engines": {
"node": ">= 0.10"
}
@@ -7373,6 +13202,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -7381,6 +13211,7 @@
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/vizion/-/vizion-2.2.1.tgz",
"integrity": "sha512-sfAcO2yeSU0CSPFI/DmZp3FsFE9T+8913nv1xWBOyzODv13fwkn6Vl7HqxGpkr9F608M+8SuFId3s+BlZqfXww==",
+ "license": "Apache-2.0",
"dependencies": {
"async": "^2.6.3",
"git-node-fs": "^1.0.0",
@@ -7395,14 +13226,26 @@
"version": "2.6.4",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
"integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
+ "license": "MIT",
"dependencies": {
"lodash": "^4.17.14"
}
},
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
"node_modules/web-streams-polyfill": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+ "license": "MIT",
"engines": {
"node": ">= 8"
}
@@ -7411,6 +13254,7 @@
"version": "0.24.5",
"resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.24.5.tgz",
"integrity": "sha512-+J/2VSHN8J47gQUAvF8KDadrfz6uFYVjxoxbKWDoXVsH2u7yLdarCnIURnrMA6uSRkgX3SdmqM5BOoQjPdSh5w==",
+ "license": "MIT",
"optional": true
},
"node_modules/which": {
@@ -7418,6 +13262,7 @@
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
},
@@ -7428,10 +13273,17 @@
"node": ">= 8"
}
},
+ "node_modules/which-module": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
+ "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
+ "license": "ISC"
+ },
"node_modules/which-typed-array": {
"version": "1.1.19",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
"integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
+ "license": "MIT",
"dependencies": {
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.8",
@@ -7453,19 +13305,54 @@
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
+ },
+ "node_modules/write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
},
"node_modules/ws": {
"version": "7.5.10",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+ "license": "MIT",
"engines": {
"node": ">=8.3.0"
},
@@ -7485,12 +13372,14 @@
"node_modules/xml": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
- "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw=="
+ "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==",
+ "license": "MIT"
},
"node_modules/xml-but-prettier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/xml-but-prettier/-/xml-but-prettier-1.0.1.tgz",
"integrity": "sha512-C2CJaadHrZTqESlH03WOyw0oZTtoy2uEg6dSDF6YRg+9GnYNub53RRemLpnvtbHDFelxMx4LajiFsYeR6XJHgQ==",
+ "license": "MIT",
"dependencies": {
"repeat-string": "^1.5.2"
}
@@ -7499,6 +13388,7 @@
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
"integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
+ "license": "MIT",
"dependencies": {
"sax": ">=0.6.0",
"xmlbuilder": "~11.0.0"
@@ -7511,36 +13401,87 @@
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "license": "MIT",
"engines": {
"node": ">=4.0"
}
},
+ "node_modules/xmlchars": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+ "license": "MIT"
+ },
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "license": "MIT",
"engines": {
"node": ">=0.4"
}
},
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
},
"node_modules/yaml": {
"version": "2.0.0-1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz",
"integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==",
+ "license": "ISC",
"engines": {
"node": ">= 6"
}
},
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=10"
},
@@ -7552,6 +13493,7 @@
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz",
"integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==",
+ "license": "MIT",
"dependencies": {
"lodash.get": "^4.4.2",
"lodash.isequal": "^4.5.0",
@@ -7571,6 +13513,7 @@
"version": "9.5.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
+ "license": "MIT",
"optional": true,
"engines": {
"node": "^12.20.0 || >=14"
@@ -7579,7 +13522,77 @@
"node_modules/zenscroll": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/zenscroll/-/zenscroll-4.0.2.tgz",
- "integrity": "sha512-jEA1znR7b4C/NnaycInCU6h/d15ZzCd1jmsruqOKnZP6WXQSMH3W2GL+OXbkruslU4h+Tzuos0HdswzRUk/Vgg=="
+ "integrity": "sha512-jEA1znR7b4C/NnaycInCU6h/d15ZzCd1jmsruqOKnZP6WXQSMH3W2GL+OXbkruslU4h+Tzuos0HdswzRUk/Vgg==",
+ "license": "Unlicense"
+ },
+ "node_modules/zip-stream": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz",
+ "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==",
+ "license": "MIT",
+ "dependencies": {
+ "archiver-utils": "^3.0.4",
+ "compress-commons": "^4.1.2",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/zip-stream/node_modules/archiver-utils": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz",
+ "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==",
+ "license": "MIT",
+ "dependencies": {
+ "glob": "^7.2.3",
+ "graceful-fs": "^4.2.0",
+ "lazystream": "^1.0.0",
+ "lodash.defaults": "^4.2.0",
+ "lodash.difference": "^4.5.0",
+ "lodash.flatten": "^4.4.0",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.union": "^4.6.0",
+ "normalize-path": "^3.0.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/zip-stream/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/zod": {
+ "version": "3.24.4",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz",
+ "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zod-to-json-schema": {
+ "version": "3.24.5",
+ "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz",
+ "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==",
+ "dev": true,
+ "license": "ISC",
+ "peerDependencies": {
+ "zod": "^3.24.1"
+ }
}
}
}
diff --git a/package.json b/package.json
index 2b01574c..f8296d10 100644
--- a/package.json
+++ b/package.json
@@ -1,36 +1,147 @@
{
- "name": "prueba-arquitectura-backend-textiles",
+ "name": "backend-textiles",
"version": "1.0.0",
- "description": "prueba de arquitectura del backend utilizando AWS para el proyecto de textiles Code&Co",
+ "description": "Backend del proyecto para Altertex del departamento CodeCode",
"main": "index.js",
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1",
- "lint": "npx eslint . --fix"
+ "start": "nodemon app.js",
+ "test": "jest",
+ "lint": "npx eslint .",
+ "lint-fix": "npx eslint . --fix"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@aws-sdk/client-dynamodb": "^3.751.0",
- "@aws-sdk/client-s3": "^3.750.0",
+ "@aws-sdk/client-s3": "^3.808.0",
"@aws-sdk/lib-dynamodb": "^3.751.0",
+ "@aws-sdk/s3-request-presigner": "^3.787.0",
+ "@aws-sdk/types": "^3.775.0",
"aws-sdk": "^2.1692.0",
"bcryptjs": "^3.0.0",
"body-parser": "^1.20.3",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
+ "csurf": "^1.11.0",
+ "date-fns": "^4.1.0",
"dotenv": "^16.4.7",
+ "exceljs": "^4.4.0",
"express": "^4.21.2",
+ "helmet": "^8.1.0",
+ "i": "^0.3.7",
+ "json2csv": "^6.0.0-alpha.2",
"jsonwebtoken": "^9.0.2",
+ "module-alias": "^2.2.3",
"multer": "^1.4.5-lts.1",
"multer-s3": "^3.0.1",
+ "mysql2": "^3.14.0",
+ "node-cron": "^3.0.3",
+ "nodemon": "^3.1.9",
"pm2": "^5.4.3",
+ "qrcode": "^1.5.4",
+ "redis": "^5.1.0",
+ "speakeasy": "^2.0.0",
+ "supertest": "^7.1.0",
"swagger-jsdoc": "^6.2.8",
- "swagger-ui": "^5.20.0",
+ "swagger-ui": "^5.21.0",
"swagger-ui-express": "^5.0.1"
},
"devDependencies": {
"@eslint/js": "^9.23.0",
- "eslint": "^9.22.0"
+ "eslint": "^9.22.0",
+ "eslint-plugin-jsdoc": "^50.6.11",
+ "jest": "^29.7.0"
+ },
+ "_moduleAliases": {
+ "@altertex/root": ".",
+ "@altertex/aut": "Autenticacion/",
+ "@altertex/aut/ctrl": "Autenticacion/Controladores/",
+ "@altertex/aut/datos": "Autenticacion/Datos/",
+ "@altertex/aut/repos": "Autenticacion/Datos/Repositorios",
+ "@altertex/aut/rutas": "Autenticacion/Rutas/",
+ "@altertex/aut/rutasInd": "Autenticacion/Rutas/RutasIndividuales",
+ "@altertex/usu": "Usuarios/",
+ "@altertex/usu/ctrl": "Usuarios/Controladores/",
+ "@altertex/usu/datos": "Usuarios/Datos/",
+ "@altertex/usu/repos": "Usuarios/Datos/Repositorios",
+ "@altertex/usu/rutas": "Usuarios/Rutas/",
+ "@altertex/usu/rutasInd": "Usuarios/Rutas/RutasIndividuales",
+ "@altertex/emp": "Empleados/",
+ "@altertex/emp/ctrl": "Empleados/Controladores/",
+ "@altertex/emp/datos": "Empleados/Datos/",
+ "@altertex/emp/repos": "Empleados/Datos/Repositorios",
+ "@altertex/emp/rutas": "Empleados/Rutas/",
+ "@altertex/emp/rutasInd": "Empleados/Rutas/RutasIndividuales",
+ "@altertex/cli": "Clientes/",
+ "@altertex/cli/ctrl": "Clientes/Controladores/",
+ "@altertex/cli/datos": "Clientes/Datos/",
+ "@altertex/cli/repos": "Clientes/Datos/Repositorios",
+ "@altertex/cli/rutas": "Clientes/Rutas/",
+ "@altertex/cli/rutasInd": "Clientes/Rutas/RutasIndividuales",
+ "@altertex/cuota": "Cuotas/",
+ "@altertex/cuota/ctrl": "Cuotas/Controladores/",
+ "@altertex/cuota/datos": "Cuotas/Datos/",
+ "@altertex/cuota/repos": "Cuotas/Datos/Repositorios",
+ "@altertex/cuota/rutas": "Cuotas/Rutas/",
+ "@altertex/cuota/rutasInd": "Cuotas/Rutas/RutasIndividuales",
+ "@altertex/config": "Configuracion/",
+ "@altertex/util": "Utilidades/",
+ "@altertex/util/bd": "Utilidades/BaseDeDatos/",
+ "@altertex/util/const": "Utilidades/Constantes/",
+ "@altertex/util/inter": "Utilidades/Intermediarios/",
+ "@altertex/util/vali": "Utilidades/Intermediarios/Validaciones",
+ "@altertex/rol": "Roles",
+ "@altertex/rol/ctrl": "Roles/Controladores",
+ "@altertex/rol/datos": "Roles/Datos",
+ "@altertex/rol/repos": "Roles/Datos/Repositorios",
+ "@altertex/rol/rutas": "Roles/Rutas",
+ "@altertex/rol/rutasInd": "Roles/Rutas/RutasIndividuales",
+ "@altertex/CRON": "CRON_JOBS/",
+ "@altertex/CRON/ctrl": "CRON_JOBS/Controladores/",
+ "@altertex/CRON/datos": "CRON_JOBS/Datos/",
+ "@altertex/CRON/repos": "CRON_JOBS/Datos/Repositorios/",
+ "@altertex/pro": "Productos/",
+ "@altertex/pro/ctrl": "Productos/Controladores/",
+ "@altertex/pro/datos": "Productos/Datos/",
+ "@altertex/pro/repos": "Productos/Datos/Repositorios",
+ "@altertex/pro/rutas": "Productos/Rutas/",
+ "@altertex/pro/rutasInd": "Productos/Rutas/RutasIndividuales",
+ "@altertex/prove": "Proveedores",
+ "@altertex/prove/ctrl": "Proveedores/Controladores/",
+ "@altertex/prove/datos": "Proveedores/Datos/",
+ "@altertex/prove/repos": "Proveedores/Datos/Repositorios",
+ "@altertex/prove/rutas": "Proveedores/Rutas/",
+ "@altertex/prove/rutasInd": "Proveedores/Rutas/RutasIndividuales",
+ "@altertex/cat": "Categorias/",
+ "@altertex/cat/ctrl": "Categorias/Controladores/",
+ "@altertex/cat/datos": "Categorias/Datos/",
+ "@altertex/cat/repos": "Categorias/Datos/Repositorios",
+ "@altertex/cat/rutas": "Categorias/Rutas/",
+ "@altertex/cat/rutasInd": "Categorias/Rutas/RutasIndividuales",
+ "@altertex/util/ser": "Utilidades/Servicios/",
+ "@altertex/setspro": "SetsProductos/",
+ "@altertex/setspro/ctrl": "SetsProductos/Controladores/",
+ "@altertex/setspro/datos": "SetsProductos/Datos/",
+ "@altertex/setspro/repos": "SetsProductos/Datos/Repositorios",
+ "@altertex/setspro/rutas": "SetsProductos/Rutas/",
+ "@altertex/setspro/rutasInd": "SetsProductos/Rutas/RutasIndividuales",
+ "@altertex/pedidos/": "Pedidos/",
+ "@altertex/pedidos/ctrl": "Pedidos/Controladores/",
+ "@altertex/pedidos/datos": "Pedidos/Datos/",
+ "@altertex/pedidos/repos": "Pedidos/Datos/Repositorios",
+ "@altertex/pedidos/rutas": "Pedidos/Rutas",
+ "@altertex/pedidos/rutasInd": "Pedidos/Rutas/RutasIndividuales",
+ "@altertex/eve": "Eventos/",
+ "@altertex/eve/ctrl": "Eventos/Controladores/",
+ "@altertex/eve/datos": "Eventos/Datos/",
+ "@altertex/eve/repos": "Eventos/Datos/Repositorios",
+ "@altertex/eve/rutas": "Eventos/Rutas/",
+ "@altertex/eve/rutasInd": "Eventos/Rutas/RutasIndividuales",
+ "@altertex/pago/ctrl": "Pagos/Controladores/",
+ "@altertex/pago/datos": "Pagos/Datos",
+ "@altertex/pago/repos": "Pagos/Datos/Repositorios/",
+ "@altertex/pago/rutas": "Pagos/Rutas/",
+ "@altertex/pago/rutas/rutasInd": "Pagos/Rutas/RutasIndividuales"
}
}
diff --git a/util/middlewares/autorizarToken.js b/util/middlewares/autorizarToken.js
deleted file mode 100644
index 48861021..00000000
--- a/util/middlewares/autorizarToken.js
+++ /dev/null
@@ -1,22 +0,0 @@
-const jwt = require("jsonwebtoken");
-
-module.exports = async (req, res, next) => {
- const token = req.cookies.token; // Get token from cookies
-
- console.log(req.cookies);
- console.log(token);
-
- if (!token) {
- return res.status(403).json({ message: "Acceso denegado" });
- }
-
- try {
- const verificado = jwt.verify(token, process.env.JWT_SECRET);
- req.user = verificado;
- console.log("Verificado");
- next();
- } catch (error) {
- console.log("no Verificado");
- res.status(401).json({ message: "Token inválido", error: error });
- }
-};
diff --git a/util/middlewares/revisarApiKey.js b/util/middlewares/revisarApiKey.js
deleted file mode 100644
index 23f62c82..00000000
--- a/util/middlewares/revisarApiKey.js
+++ /dev/null
@@ -1,9 +0,0 @@
-module.exports = (nombreHeader, mensajeError = "Api key invalida") => {
- return (req, res, next) => {
- const valorHeader = req.get(nombreHeader);
- if (valorHeader !== process.env.API_KEY) {
- return res.status(400).json({ message: mensajeError });
- }
- next();
- };
-};
diff --git a/util/services/enviarDatos.js b/util/services/enviarDatos.js
deleted file mode 100644
index fdaf4d8c..00000000
--- a/util/services/enviarDatos.js
+++ /dev/null
@@ -1,14 +0,0 @@
-const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
-const { DynamoDBDocumentClient, PutCommand } = require("@aws-sdk/lib-dynamodb");
-
-const clienteDynamo = new DynamoDBClient({ region: "us-east-1" });
-const db = DynamoDBDocumentClient.from(clienteDynamo);
-
-module.exports = async (nombreTabla, modelo) => {
- const comando = new PutCommand({
- TableName: nombreTabla,
- Item: modelo,
- });
-
- return db.send(comando);
-};
diff --git a/util/services/enviarS3.js b/util/services/enviarS3.js
deleted file mode 100644
index cd6aef0e..00000000
--- a/util/services/enviarS3.js
+++ /dev/null
@@ -1,16 +0,0 @@
-const { S3Client, PutObjectCommand } = require("@aws-sdk/client-s3");
-
-const s3 = new S3Client({
- region: "us-east-1",
-});
-
-module.exports = async (params) => {
- try {
- await s3.send(new PutObjectCommand(params));
- const fileName = params.Key;
- return `https://${process.env.AWS_BUCKET_NAME}.s3.${process.env.AWS_REGION}.amazonaws.com/uploads/${fileName}`;
- } catch (error) {
- console.error("Error uploading to S3:", error);
- throw new Error("Failed to upload file to S3");
- }
-};
diff --git a/util/services/generarNombreUnico.js b/util/services/generarNombreUnico.js
deleted file mode 100644
index 967b004a..00000000
--- a/util/services/generarNombreUnico.js
+++ /dev/null
@@ -1,7 +0,0 @@
-const crypto = require("crypto");
-const path = require("path");
-
-module.exports = (originalName) => {
- const randomBytes = crypto.randomBytes(16).toString("hex");
- return `${Date.now()}-${randomBytes}${path.extname(originalName)}`;
-};
diff --git a/util/services/recibirDatos.js b/util/services/recibirDatos.js
deleted file mode 100644
index d0382cbf..00000000
--- a/util/services/recibirDatos.js
+++ /dev/null
@@ -1,14 +0,0 @@
-const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
-const { DynamoDBDocumentClient, GetCommand } = require("@aws-sdk/lib-dynamodb");
-
-const clienteDynamo = new DynamoDBClient({ region: "us-east-1" });
-const db = DynamoDBDocumentClient.from(clienteDynamo);
-
-module.exports = async (nombreTabla, llaves) => {
- const comando = new GetCommand({
- TableName: nombreTabla,
- Key: llaves,
- });
- const response = await db.send(comando);
- return response.Item;
-};