diff --git a/backend/.editorconfig b/backend/.editorconfig new file mode 100644 index 0000000..11695db --- /dev/null +++ b/backend/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +end_of_line = lf +indent_style = space +indent_size = 2 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/backend/.env.example b/backend/.env.example new file mode 100644 index 0000000..fe43ee5 --- /dev/null +++ b/backend/.env.example @@ -0,0 +1,35 @@ +NODE_ENV= +BACKEND_URL=http://localhost +FRONTEND_URL=http://localhost:3000 +PROXY_PORT=8080 +PORT=8080 + +DB_DIALECT=postgres +DB_HOST=localhost +DB_PORT=5432 +DB_USER=user +DB_PASS=senha +DB_NAME=db_name + +JWT_SECRET=kZaOTd+YZpjRUyyuQUpigJaEMk4vcW4YOymKPZX0Ts8= +JWT_REFRESH_SECRET=dBSXqFg9TaNUEDXVp6fhMTRLBysP+j2DSqf7+raxD3A= + +REDIS_URI=redis://:123456@127.0.0.1:6379 +REDIS_OPT_LIMITER_MAX=1 +REDIS_OPT_LIMITER_DURATION=3000 + +USER_LIMIT=10000 +CONNECTIONS_LIMIT=100000 +CLOSED_SEND_BY_ME=true + +GERENCIANET_SANDBOX=false +GERENCIANET_CLIENT_ID=Client_Id_Gerencianet +GERENCIANET_CLIENT_SECRET=Client_Secret_Gerencianet +GERENCIANET_PIX_CERT=certificado-Gerencianet +GERENCIANET_PIX_KEY=chave pix gerencianet + +MAIL_HOST="smtp.hostinger.com" +MAIL_USER="contato@seusite.com" +MAIL_PASS="senha" +MAIL_FROM="Recuperar Senha " +MAIL_PORT="465" diff --git a/backend/.eslintignore b/backend/.eslintignore new file mode 100644 index 0000000..77b9a34 --- /dev/null +++ b/backend/.eslintignore @@ -0,0 +1,3 @@ +/*.js +node_modules +dist diff --git a/backend/.eslintrc.json b/backend/.eslintrc.json new file mode 100644 index 0000000..aa015fa --- /dev/null +++ b/backend/.eslintrc.json @@ -0,0 +1,49 @@ +{ + "env": { + "es2021": true, + "node": true, + "jest": true + }, + "extends": [ + "airbnb-base", + "plugin:@typescript-eslint/recommended", + "prettier/@typescript-eslint", + "plugin:prettier/recommended" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 12, + "sourceType": "module" + }, + "plugins": ["@typescript-eslint", "prettier"], + "rules": { + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { "argsIgnorePattern": "_" } + ], + "import/prefer-default-export": "off", + "no-console": "off", + "no-param-reassign": "off", + "prettier/prettier": "error", + "import/extensions": [ + "error", + "ignorePackages", + { + "ts": "never" + } + ], + "quotes": [ + 1, + "double", + { + "avoidEscape": true + } + ] + }, + "settings": { + "import/resolver": { + "typescript": {} + } + } +} diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 0000000..11365aa --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1,13 @@ +node_modules +public/* +!public/logotipos/ +!public/.gitkeep +dist +.env +.env.test +package-lock.json +yarn.lock +yarn-error.log +/src/config/sentry.js +coverage.data +coverage/ diff --git a/backend/.sequelizerc b/backend/.sequelizerc new file mode 100644 index 0000000..264f851 --- /dev/null +++ b/backend/.sequelizerc @@ -0,0 +1,8 @@ +const { resolve } = require("path"); + +module.exports = { + "config": resolve(__dirname, "dist", "config", "database.js"), + "modules-path": resolve(__dirname, "dist", "models"), + "migrations-path": resolve(__dirname, "dist", "database", "migrations"), + "seeders-path": resolve(__dirname, "dist", "database", "seeds") +}; diff --git a/backend/certs/coloque_seus_certificado_aqui b/backend/certs/coloque_seus_certificado_aqui new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/backend/certs/coloque_seus_certificado_aqui @@ -0,0 +1 @@ + diff --git a/backend/ecosystem.config.js b/backend/ecosystem.config.js new file mode 100644 index 0000000..626adc7 --- /dev/null +++ b/backend/ecosystem.config.js @@ -0,0 +1,9 @@ +module.exports = [{ + script: 'dist/server.js', + name: 'beta-back', + exec_mode: 'fork', + cron_restart: '05 00 * * *', + max_memory_restart: '769M', // Configuração para reiniciar quando atingir 769 MB de memória + node_args: '--max-old-space-size=769', // Limite de memória do Node.js para 769 MB + watch: false +}] \ No newline at end of file diff --git a/backend/jest.config.js b/backend/jest.config.js new file mode 100644 index 0000000..76c1b57 --- /dev/null +++ b/backend/jest.config.js @@ -0,0 +1,186 @@ +/* + * For a detailed explanation regarding each configuration property, visit: + * https://jestjs.io/docs/en/configuration.html + */ + +module.exports = { + // All imported modules in your tests should be mocked automatically + // automock: false, + + // Stop running tests after `n` failures + bail: 1, + + // The directory where Jest should store its cached dependency information + // cacheDirectory: "/tmp/jest_rs", + + // Automatically clear mock calls and instances between every test + clearMocks: true, + + // Indicates whether the coverage information should be collected while executing the test + collectCoverage: true, + + // An array of glob patterns indicating a set of files for which coverage information should be collected + collectCoverageFrom: ["/src/services/**/*.ts"], + + // The directory where Jest should output its coverage files + coverageDirectory: "coverage", + + // An array of regexp pattern strings used to skip coverage collection + // coveragePathIgnorePatterns: [ + // "/node_modules/" + // ], + + // Indicates which provider should be used to instrument code for coverage + coverageProvider: "v8", + + // A list of reporter names that Jest uses when writing coverage reports + coverageReporters: ["text", "lcov"], + + // An object that configures minimum threshold enforcement for coverage results + // coverageThreshold: undefined, + + // A path to a custom dependency extractor + // dependencyExtractor: undefined, + + // Make calling deprecated APIs throw helpful error messages + // errorOnDeprecated: false, + + // Force coverage collection from ignored files using an array of glob patterns + // forceCoverageMatch: [], + + // A path to a module which exports an async function that is triggered once before all test suites + // globalSetup: undefined, + + // A path to a module which exports an async function that is triggered once after all test suites + // globalTeardown: undefined, + + // A set of global variables that need to be available in all test environments + // globals: {}, + + // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. + // maxWorkers: "50%", + + // An array of directory names to be searched recursively up from the requiring module's location + // moduleDirectories: [ + // "node_modules" + // ], + + // An array of file extensions your modules use + // moduleFileExtensions: [ + // "js", + // "json", + // "jsx", + // "ts", + // "tsx", + // "node" + // ], + + // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module + // moduleNameMapper: {}, + + // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader + // modulePathIgnorePatterns: [], + + // Activates notifications for test results + // notify: false, + + // An enum that specifies notification mode. Requires { notify: true } + // notifyMode: "failure-change", + + // A preset that is used as a base for Jest's configuration + preset: "ts-jest", + + // Run tests from one or more projects + // projects: undefined, + + // Use this configuration option to add custom reporters to Jest + // reporters: undefined, + + // Automatically reset mock state between every test + // resetMocks: false, + + // Reset the module registry before running each individual test + // resetModules: false, + + // A path to a custom resolver + // resolver: undefined, + + // Automatically restore mock state between every test + // restoreMocks: false, + + // The root directory that Jest should scan for tests and modules within + // rootDir: undefined, + + // A list of paths to directories that Jest should use to search for files in + // roots: [ + // "" + // ], + + // Allows you to use a custom runner instead of Jest's default test runner + // runner: "jest-runner", + + // The paths to modules that run some code to configure or set up the testing environment before each test + // setupFiles: [], + + // A list of paths to modules that run some code to configure or set up the testing framework before each test + // setupFilesAfterEnv: [], + + // The number of seconds after which a test is considered as slow and reported as such in the results. + // slowTestThreshold: 5, + + // A list of paths to snapshot serializer modules Jest should use for snapshot testing + // snapshotSerializers: [], + + // The test environment that will be used for testing + testEnvironment: "node", + + // Options that will be passed to the testEnvironment + // testEnvironmentOptions: {}, + + // Adds a location field to test results + // testLocationInResults: false, + + // The glob patterns Jest uses to detect test files + testMatch: ["**/__tests__/**/*.spec.ts"] + + // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped + // testPathIgnorePatterns: [ + // "/node_modules/" + // ], + + // The regexp pattern or array of patterns that Jest uses to detect test files + // testRegex: [], + + // This option allows the use of a custom results processor + // testResultsProcessor: undefined, + + // This option allows use of a custom test runner + // testRunner: "jasmine2", + + // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href + // testURL: "http://localhost", + + // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout" + // timers: "real", + + // A map from regular expressions to paths to transformers + // transform: undefined, + + // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation + // transformIgnorePatterns: [ + // "/node_modules/", + // "\\.pnp\\.[^\\/]+$" + // ], + + // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them + // unmockedModulePathPatterns: undefined, + + // Indicates whether each individual test should be reported during the run + // verbose: undefined, + + // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode + // watchPathIgnorePatterns: [], + + // Whether to use watchman for file crawling + // watchman: true, +}; diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 0000000..aa6ad37 --- /dev/null +++ b/backend/package.json @@ -0,0 +1,113 @@ +{ + "name": "backend", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "build": "tsc --sourceMap false", + "devbuild": "tsc --sourceMap true", + "watch": "tsc -w", + "start": "node --max-old-space-size=8096 dist/server.js", + "dev": "tsc-watch --onSuccess \"node --max-old-space-size=8096 --trace-warnings ./dist/server.js\"", + "dev:server": "node --max-old-space-size=8096 -r ts-node/register src/server.ts", + "db:migrate": "npx sequelize db:migrate", + "db:seed": "sequelize db:seed:all", + "pretest": "NODE_ENV=test sequelize db:migrate && NODE_ENV=test sequelize db:seed:all", + "test": "NODE_ENV=test jest", + "posttest": "NODE_ENV=test sequelize db:migrate:undo:all", + "lint": "eslint src/**/*.ts" + }, + "author": "", + "license": "MIT", + "dependencies": { + "@adiwajshing/keyed-db": "^0.2.4", + "@ffmpeg-installer/ffmpeg": "^1.1.0", + "@hapi/boom": "^9.1.4", + "@sentry/node": "^6.18.1", + "@types/fs-extra": "^11.0.4", + "@whiskeysockets/baileys": "^6.7.9", + "async-mutex": "^0.4.1", + "bcryptjs": "^2.4.3", + "body-parser": "^1.20.2", + "bull": "^4.8.2", + "cookie-parser": "^1.4.6", + "cors": "^2.8.5", + "cron": "^2.1.0", + "date-fns": "^2.28.0", + "dotenv": "^16.0.0", + "express": "^4.17.3", + "express-async-errors": "^3.1.1", + "ffmpeg-static": "^5.2.0", + "fluent-ffmpeg": "^2.1.3", + "gn-api-sdk-typescript": "^1.0.7", + "http-graceful-shutdown": "^3.1.6", + "image-size": "^1.2.0", + "ioredis": "^5.4.1", + "jsonwebtoken": "^8.5.1", + "microsoft-cognitiveservices-speech-sdk": "1.31.0", + "multer": "^1.4.4", + "mustache": "^4.2.0", + "mysql2": "^2.2.5", + "node-cache": "^5.1.2", + "node-cron": "^3.0.2", + "nodemailer": "^6.8.0", + "notificamehubsdk": "^0.0.19", + "openai": "3.3.0", + "pg": "^8.7.3", + "pino": "^7.8.0", + "pino-pretty": "^10.0.0", + "puppeteer": "^19.4.0", + "qrcode-terminal": "^0.12.0", + "reflect-metadata": "^0.1.13", + "request": "2.88.2", + "sequelize": "^5.22.3", + "sequelize-cli": "^5.5.1", + "sequelize-typescript": "^1.1.0", + "socket.io": "^4.7.4", + "uuid": "^8.3.2", + "xlsx": "^0.18.3", + "yup": "^0.32.11" + }, + "devDependencies": { + "@types/bcryptjs": "^2.4.2", + "@types/bluebird": "^3.5.36", + "@types/chance": "^1.1.3", + "@types/cookie-parser": "^1.4.2", + "@types/cors": "^2.8.12", + "@types/express": "^4.17.13", + "@types/factory-girl": "^5.0.8", + "@types/faker": "^5.1.3", + "@types/fluent-ffmpeg": "^2.1.26", + "@types/fs-extra": "^11.0.4", + "@types/image-size": "^0.7.0", + "@types/ioredis": "^5.0.0", + "@types/jest": "^27.4.1", + "@types/jsonwebtoken": "^8.5.0", + "@types/multer": "^1.4.7", + "@types/mustache": "^4.1.2", + "@types/node": "^14.11.8", + "@types/pino-pretty": "~4.7.1", + "@types/supertest": "^2.0.11", + "@types/uuid": "^8.3.4", + "@types/validator": "^13.1.0", + "@types/yup": "^0.29.13", + "@typescript-eslint/eslint-plugin": "^5.13.0", + "@typescript-eslint/parser": "^5.13.0", + "chance": "^1.1.8", + "eslint": "^8.10.0", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-config-prettier": "^8.5.0", + "eslint-import-resolver-typescript": "^2.5.0", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-prettier": "^4.0.0", + "factory-girl": "^5.0.4", + "faker": "^5.1.0", + "jest": "^27.5.1", + "nodemon": "^2.0.15", + "prettier": "^2.5.1", + "supertest": "^6.2.2", + "ts-jest": "^27.1.3", + "ts-node-dev": "^1.1.8", + "typescript": "^4.6.3" + } +} diff --git a/backend/prettier.config.js b/backend/prettier.config.js new file mode 100644 index 0000000..2821955 --- /dev/null +++ b/backend/prettier.config.js @@ -0,0 +1,5 @@ +module.exports = { + singleQuote: false, + trailingComma: "none", + arrowParens: "avoid" +}; diff --git a/backend/public/logotipos/android-chrome-192x192.png b/backend/public/logotipos/android-chrome-192x192.png new file mode 100644 index 0000000..59d1ec2 Binary files /dev/null and b/backend/public/logotipos/android-chrome-192x192.png differ diff --git a/backend/public/logotipos/android-chrome-512x512.png b/backend/public/logotipos/android-chrome-512x512.png new file mode 100644 index 0000000..c90d5b1 Binary files /dev/null and b/backend/public/logotipos/android-chrome-512x512.png differ diff --git a/backend/public/logotipos/apple-touch-icon.png b/backend/public/logotipos/apple-touch-icon.png new file mode 100644 index 0000000..916209a Binary files /dev/null and b/backend/public/logotipos/apple-touch-icon.png differ diff --git a/backend/public/logotipos/facebook.png b/backend/public/logotipos/facebook.png new file mode 100644 index 0000000..6944c49 Binary files /dev/null and b/backend/public/logotipos/facebook.png differ diff --git a/backend/public/logotipos/favicon-16x16.png b/backend/public/logotipos/favicon-16x16.png new file mode 100644 index 0000000..8d78fe6 Binary files /dev/null and b/backend/public/logotipos/favicon-16x16.png differ diff --git a/backend/public/logotipos/favicon-256x256.png b/backend/public/logotipos/favicon-256x256.png new file mode 100644 index 0000000..5e77ffe Binary files /dev/null and b/backend/public/logotipos/favicon-256x256.png differ diff --git a/backend/public/logotipos/favicon-32x32.png b/backend/public/logotipos/favicon-32x32.png new file mode 100644 index 0000000..5bac117 Binary files /dev/null and b/backend/public/logotipos/favicon-32x32.png differ diff --git a/backend/public/logotipos/favicon.ico b/backend/public/logotipos/favicon.ico new file mode 100644 index 0000000..594a202 Binary files /dev/null and b/backend/public/logotipos/favicon.ico differ diff --git a/backend/public/logotipos/favicon.png b/backend/public/logotipos/favicon.png new file mode 100644 index 0000000..c90d5b1 Binary files /dev/null and b/backend/public/logotipos/favicon.png differ diff --git a/backend/public/logotipos/interno.png b/backend/public/logotipos/interno.png new file mode 100644 index 0000000..82b59b3 Binary files /dev/null and b/backend/public/logotipos/interno.png differ diff --git a/backend/public/logotipos/login.png b/backend/public/logotipos/login.png new file mode 100644 index 0000000..267718c Binary files /dev/null and b/backend/public/logotipos/login.png differ diff --git a/backend/public/logotipos/logo.png b/backend/public/logotipos/logo.png new file mode 100644 index 0000000..267718c Binary files /dev/null and b/backend/public/logotipos/logo.png differ diff --git a/backend/public/logotipos/logo_meta.png b/backend/public/logotipos/logo_meta.png new file mode 100644 index 0000000..890cc84 Binary files /dev/null and b/backend/public/logotipos/logo_meta.png differ diff --git a/backend/public/logotipos/logo_typebot.png b/backend/public/logotipos/logo_typebot.png new file mode 100644 index 0000000..ae274ed Binary files /dev/null and b/backend/public/logotipos/logo_typebot.png differ diff --git a/backend/public/logotipos/logo_w.png b/backend/public/logotipos/logo_w.png new file mode 100644 index 0000000..68a66d8 Binary files /dev/null and b/backend/public/logotipos/logo_w.png differ diff --git a/backend/public/logotipos/mstile-150x150.png b/backend/public/logotipos/mstile-150x150.png new file mode 100644 index 0000000..7c22f8c Binary files /dev/null and b/backend/public/logotipos/mstile-150x150.png differ diff --git a/backend/public/logotipos/signup.png b/backend/public/logotipos/signup.png new file mode 100644 index 0000000..ff238e5 Binary files /dev/null and b/backend/public/logotipos/signup.png differ diff --git a/backend/public/logotipos/tela-login.png b/backend/public/logotipos/tela-login.png new file mode 100644 index 0000000..03b5e82 Binary files /dev/null and b/backend/public/logotipos/tela-login.png differ diff --git a/backend/src/@types/express.d.ts b/backend/src/@types/express.d.ts new file mode 100644 index 0000000..113a3e7 --- /dev/null +++ b/backend/src/@types/express.d.ts @@ -0,0 +1,5 @@ +declare namespace Express { + export interface Request { + user: { id: string; profile: string; companyId: number }; + } +} diff --git a/backend/src/@types/qrcode-terminal.d.ts b/backend/src/@types/qrcode-terminal.d.ts new file mode 100644 index 0000000..3b59fed --- /dev/null +++ b/backend/src/@types/qrcode-terminal.d.ts @@ -0,0 +1 @@ +declare module "qrcode-terminal"; diff --git a/backend/src/app.ts b/backend/src/app.ts new file mode 100644 index 0000000..c88ea35 --- /dev/null +++ b/backend/src/app.ts @@ -0,0 +1,53 @@ +import * as Sentry from "@sentry/node"; +import cookieParser from "cookie-parser"; +import cors from "cors"; +import express, { NextFunction, Request, Response } from "express"; +import "express-async-errors"; +import "reflect-metadata"; +import "./bootstrap"; + +import bodyParser from 'body-parser'; +import uploadConfig from "./config/upload"; +import "./database"; +import AppError from "./errors/AppError"; +import { messageQueue, sendScheduledMessages } from "./queues"; +import routes from "./routes"; +import { logger } from "./utils/logger"; + +Sentry.init({ dsn: process.env.SENTRY_DSN }); + +const app = express(); + +app.set("queues", { + messageQueue, + sendScheduledMessages +}); + +const bodyparser = require('body-parser'); +app.use(bodyParser.json({ limit: '10mb' })); + +app.use( + cors({ + credentials: true, + origin: process.env.FRONTEND_URL + }) +); +app.use(cookieParser()); +app.use(express.json()); +app.use(Sentry.Handlers.requestHandler()); +app.use("/public", express.static(uploadConfig.directory)); +app.use(routes); + +app.use(Sentry.Handlers.errorHandler()); + +app.use(async (err: Error, req: Request, res: Response, _: NextFunction) => { + if (err instanceof AppError) { + logger.warn(err); + return res.status(err.statusCode).json({ error: err.message }); + } + + logger.error(err); + return res.status(500).json({ error: "Internal server error" }); +}); + +export default app; diff --git a/backend/src/bootstrap.ts b/backend/src/bootstrap.ts new file mode 100644 index 0000000..03fffb5 --- /dev/null +++ b/backend/src/bootstrap.ts @@ -0,0 +1,5 @@ +import dotenv from "dotenv"; + +dotenv.config({ + path: process.env.NODE_ENV === "test" ? ".env.test" : ".env" +}); diff --git a/backend/src/config/Gn.ts b/backend/src/config/Gn.ts new file mode 100644 index 0000000..d4cbb91 --- /dev/null +++ b/backend/src/config/Gn.ts @@ -0,0 +1,13 @@ +import path from "path"; + +const cert = path.join( + __dirname, + `../../certs/${process.env.GERENCIANET_PIX_CERT}.p12` +); + +export = { + sandbox: false, + client_id: process.env.GERENCIANET_CLIENT_ID as string, + client_secret: process.env.GERENCIANET_CLIENT_SECRET as string, + pix_cert: cert +}; diff --git a/backend/src/config/auth.ts b/backend/src/config/auth.ts new file mode 100644 index 0000000..6f8c5fd --- /dev/null +++ b/backend/src/config/auth.ts @@ -0,0 +1,6 @@ +export default { + secret: process.env.JWT_SECRET || "mysecret", + expiresIn: "15m", + refreshSecret: process.env.JWT_REFRESH_SECRET || "myanothersecret", + refreshExpiresIn: "7d" +}; diff --git a/backend/src/config/database.ts b/backend/src/config/database.ts new file mode 100644 index 0000000..d5e452b --- /dev/null +++ b/backend/src/config/database.ts @@ -0,0 +1,16 @@ +import "../bootstrap"; + +module.exports = { + define: { + charset: "utf8mb4", + collate: "utf8mb4_bin" + }, + dialect: process.env.DB_DIALECT || "mysql", + timezone: "-03:00", + host: process.env.DB_HOST, + port: process.env.DB_PORT || 3306, + database: process.env.DB_NAME, + username: process.env.DB_USER, + password: process.env.DB_PASS, + logging: process.env.DB_DEBUG === "true" +}; diff --git a/backend/src/config/redis.ts b/backend/src/config/redis.ts new file mode 100644 index 0000000..43118e2 --- /dev/null +++ b/backend/src/config/redis.ts @@ -0,0 +1,3 @@ +export const REDIS_URI_CONNECTION = process.env.REDIS_URI || ""; +export const REDIS_OPT_LIMITER_MAX = process.env.REDIS_OPT_LIMITER_MAX || 1; +export const REDIS_OPT_LIMITER_DURATION = process.env.REDIS_OPT_LIMITER_DURATION || 3000; diff --git a/backend/src/config/upload.ts b/backend/src/config/upload.ts new file mode 100644 index 0000000..383cf5a --- /dev/null +++ b/backend/src/config/upload.ts @@ -0,0 +1,50 @@ +import path from "path"; +import multer from "multer"; +import fs from "fs"; +import Whatsapp from "../models/Whatsapp"; +import { isEmpty, isNil } from "lodash"; + +const publicFolder = path.resolve(__dirname, "..", "..", "public"); + +export default { + directory: publicFolder, + storage: multer.diskStorage({ + destination: async function (req, file, cb) { + + let companyId; + companyId = req.user?.companyId + const { typeArch, fileId } = req.body; + + if (companyId === undefined && isNil(companyId) && isEmpty(companyId)) { + const authHeader = req.headers.authorization; + const [, token] = authHeader.split(" "); + const whatsapp = await Whatsapp.findOne({ where: { token } }); + companyId = whatsapp.companyId; + } + let folder; + + if (typeArch && typeArch !== "announcements" && typeArch !== "logo") { + folder = path.resolve(publicFolder, `company${companyId}`, typeArch, fileId ? fileId : "") + } else if (typeArch && typeArch === "announcements") { + folder = path.resolve(publicFolder, typeArch) + } else if (typeArch === "logo") { + folder = path.resolve(publicFolder) + } + else { + folder = path.resolve(publicFolder, `company${companyId}`) + } + + if (!fs.existsSync(folder)) { + fs.mkdirSync(folder, { recursive: true }) + fs.chmodSync(folder, 0o777) + } + return cb(null, folder); + }, + filename(req, file, cb) { + const { typeArch } = req.body; + + const fileName = typeArch && typeArch !== "announcements" ? file.originalname.replace('/', '-').replace(/ /g, "_") : new Date().getTime() + '_' + file.originalname.replace('/', '-').replace(/ /g, "_"); + return cb(null, fileName); + } + }) +}; diff --git a/backend/src/config/uploadlogo.ts b/backend/src/config/uploadlogo.ts new file mode 100644 index 0000000..26c634c --- /dev/null +++ b/backend/src/config/uploadlogo.ts @@ -0,0 +1,19 @@ +import path from "path"; +import multer from "multer"; + +const publicFolder = path.resolve(__dirname, "..", "..", "public/logotipos"); + +export default { + directory: publicFolder, + + storage: multer.diskStorage({ + destination: publicFolder, + filename(req, file, cb) { + + + const desiredFileName = req.query.ref + path.extname(file.originalname); + + return cb(null, desiredFileName); + } + }) +}; diff --git a/backend/src/config/uploadquick.ts b/backend/src/config/uploadquick.ts new file mode 100644 index 0000000..acab9be --- /dev/null +++ b/backend/src/config/uploadquick.ts @@ -0,0 +1,47 @@ +import path from "path"; +import multer from "multer"; +import fs from "fs"; +import Whatsapp from "../models/Whatsapp"; +import { isEmpty, isNil } from "lodash"; + +const publicFolder = path.resolve(__dirname, "..", "..", "public"); + +export default { + directory: publicFolder, + storage: multer.diskStorage({ + destination: async function (req, file, cb) { + let companyId; + + if (req.user?.companyId) { + companyId = req.user.companyId; + } else { + const authHeader = req.headers.authorization; + const [, token] = authHeader.split(" "); + const whatsapp = await Whatsapp.findOne({ where: { token } }); + companyId = whatsapp.companyId; + } + + const companyFolder = `${publicFolder}/company${companyId}`; + + // Criar a pasta company{companyId} caso ela não exista + if (!fs.existsSync(companyFolder)) { + fs.mkdirSync(companyFolder, { recursive: true }); + fs.chmodSync(companyFolder, 0o777); + } + + const folder = `${companyFolder}/quick/`; + + // Criar a pasta quick/ caso ela não exista + if (!fs.existsSync(folder)) { + fs.mkdirSync(folder, { recursive: true }); + fs.chmodSync(folder, 0o777); + } + + return cb(null, folder); + }, + filename(req, file, cb) { + const fileName = `${new Date().getTime()}_${file.originalname.replace("/", "-")}`; + return cb(null, fileName); + } + }) +}; \ No newline at end of file diff --git a/backend/src/controllers/AnnouncementController.ts b/backend/src/controllers/AnnouncementController.ts new file mode 100644 index 0000000..3d3a3a4 --- /dev/null +++ b/backend/src/controllers/AnnouncementController.ts @@ -0,0 +1,205 @@ +import * as Yup from "yup"; +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; +import { head } from "lodash"; +import fs from "fs"; +import path from "path"; + +import ListService from "../services/AnnouncementService/ListService"; +import CreateService from "../services/AnnouncementService/CreateService"; +import ShowService from "../services/AnnouncementService/ShowService"; +import UpdateService from "../services/AnnouncementService/UpdateService"; +import DeleteService from "../services/AnnouncementService/DeleteService"; +import FindService from "../services/AnnouncementService/FindService"; + +import Announcement from "../models/Announcement"; + +import AppError from "../errors/AppError"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; + companyId: string | number; +}; + +type StoreData = { + priority: string; + title: string; + text: string; + status: string; + companyId: number; + mediaPath?: string; + mediaName?: string; +}; + +type FindParams = { + companyId: string; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + + const { records, count, hasMore } = await ListService({ + searchParam, + pageNumber + }); + + return res.json({ records, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + const data = req.body as StoreData; + + const schema = Yup.object().shape({ + title: Yup.string().required() + }); + + try { + await schema.validate(data); + } catch (err: any) { + throw new AppError(err.message); + } + + const record = await CreateService({ + ...data, + companyId + }); + + const io = getIO(); + io.emit(`company-announcement`, { + action: "create", + record + }); + + return res.status(200).json(record); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const record = await ShowService(id); + + return res.status(200).json(record); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const data = req.body as StoreData; + + const schema = Yup.object().shape({ + title: Yup.string().required() + }); + + try { + await schema.validate(data); + } catch (err: any) { + throw new AppError(err.message); + } + + const { id } = req.params; + + const record = await UpdateService({ + ...data, + id + }); + + const io = getIO(); + io.emit(`company-announcement`, { + action: "update", + record + }); + + return res.status(200).json(record); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const { companyId } = req.user; + + await DeleteService(id); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-announcement`, { + action: "delete", + id + }); + + return res.status(200).json({ message: "Announcement deleted" }); +}; + +export const findList = async ( + req: Request, + res: Response +): Promise => { + const params = req.query as FindParams; + const records: Announcement[] = await FindService(params); + + return res.status(200).json(records); +}; + +export const mediaUpload = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const files = req.files as Express.Multer.File[]; + const file = head(files); + + try { + const announcement = await Announcement.findByPk(id); + + await announcement.update({ + mediaPath: file.filename, + mediaName: file.originalname + }); + await announcement.reload(); + + const io = getIO(); + io.emit(`company-announcement`, { + action: "update", + record: announcement + }); + + return res.send({ mensagem: "Mensagem enviada" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; + +export const deleteMedia = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + + try { + const announcement = await Announcement.findByPk(id); + const filePath = path.resolve("public", announcement.mediaPath); + const fileExists = fs.existsSync(filePath); + if (fileExists) { + fs.unlinkSync(filePath); + } + + await announcement.update({ + mediaPath: null, + mediaName: null + }); + await announcement.reload(); + + const io = getIO(); + io.emit(`company-announcement`, { + action: "update", + record: announcement + }); + + return res.send({ mensagem: "Arquivo excluído" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; diff --git a/backend/src/controllers/AnnouncementController_error.ts b/backend/src/controllers/AnnouncementController_error.ts new file mode 100644 index 0000000..3d3a3a4 --- /dev/null +++ b/backend/src/controllers/AnnouncementController_error.ts @@ -0,0 +1,205 @@ +import * as Yup from "yup"; +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; +import { head } from "lodash"; +import fs from "fs"; +import path from "path"; + +import ListService from "../services/AnnouncementService/ListService"; +import CreateService from "../services/AnnouncementService/CreateService"; +import ShowService from "../services/AnnouncementService/ShowService"; +import UpdateService from "../services/AnnouncementService/UpdateService"; +import DeleteService from "../services/AnnouncementService/DeleteService"; +import FindService from "../services/AnnouncementService/FindService"; + +import Announcement from "../models/Announcement"; + +import AppError from "../errors/AppError"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; + companyId: string | number; +}; + +type StoreData = { + priority: string; + title: string; + text: string; + status: string; + companyId: number; + mediaPath?: string; + mediaName?: string; +}; + +type FindParams = { + companyId: string; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + + const { records, count, hasMore } = await ListService({ + searchParam, + pageNumber + }); + + return res.json({ records, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + const data = req.body as StoreData; + + const schema = Yup.object().shape({ + title: Yup.string().required() + }); + + try { + await schema.validate(data); + } catch (err: any) { + throw new AppError(err.message); + } + + const record = await CreateService({ + ...data, + companyId + }); + + const io = getIO(); + io.emit(`company-announcement`, { + action: "create", + record + }); + + return res.status(200).json(record); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const record = await ShowService(id); + + return res.status(200).json(record); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const data = req.body as StoreData; + + const schema = Yup.object().shape({ + title: Yup.string().required() + }); + + try { + await schema.validate(data); + } catch (err: any) { + throw new AppError(err.message); + } + + const { id } = req.params; + + const record = await UpdateService({ + ...data, + id + }); + + const io = getIO(); + io.emit(`company-announcement`, { + action: "update", + record + }); + + return res.status(200).json(record); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const { companyId } = req.user; + + await DeleteService(id); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-announcement`, { + action: "delete", + id + }); + + return res.status(200).json({ message: "Announcement deleted" }); +}; + +export const findList = async ( + req: Request, + res: Response +): Promise => { + const params = req.query as FindParams; + const records: Announcement[] = await FindService(params); + + return res.status(200).json(records); +}; + +export const mediaUpload = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const files = req.files as Express.Multer.File[]; + const file = head(files); + + try { + const announcement = await Announcement.findByPk(id); + + await announcement.update({ + mediaPath: file.filename, + mediaName: file.originalname + }); + await announcement.reload(); + + const io = getIO(); + io.emit(`company-announcement`, { + action: "update", + record: announcement + }); + + return res.send({ mensagem: "Mensagem enviada" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; + +export const deleteMedia = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + + try { + const announcement = await Announcement.findByPk(id); + const filePath = path.resolve("public", announcement.mediaPath); + const fileExists = fs.existsSync(filePath); + if (fileExists) { + fs.unlinkSync(filePath); + } + + await announcement.update({ + mediaPath: null, + mediaName: null + }); + await announcement.reload(); + + const io = getIO(); + io.emit(`company-announcement`, { + action: "update", + record: announcement + }); + + return res.send({ mensagem: "Arquivo excluído" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; diff --git a/backend/src/controllers/CampaignController.ts b/backend/src/controllers/CampaignController.ts new file mode 100644 index 0000000..e6ee294 --- /dev/null +++ b/backend/src/controllers/CampaignController.ts @@ -0,0 +1,289 @@ +import { Request, Response } from "express"; +import fs from "fs"; +import { head } from "lodash"; +import path from "path"; +import * as Yup from "yup"; +import { getIO } from "../libs/socket"; + +import CreateService from "../services/CampaignService/CreateService"; +import DeleteService from "../services/CampaignService/DeleteService"; +import FindService from "../services/CampaignService/FindService"; +import ListService from "../services/CampaignService/ListService"; +import ShowService from "../services/CampaignService/ShowService"; +import UpdateService from "../services/CampaignService/UpdateService"; + +import Campaign from "../models/Campaign"; + +import AppError from "../errors/AppError"; +import Contact from "../models/Contact"; +import ContactList from "../models/ContactList"; +import ContactListItem from "../models/ContactListItem"; +import Ticket from "../models/Ticket"; +import TicketTag from "../models/TicketTag"; +import { CancelService } from "../services/CampaignService/CancelService"; +import { RestartService } from "../services/CampaignService/RestartService"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; + companyId: string | number; +}; + +type StoreData = { + name: string; + status: string; + confirmation: boolean; + scheduledAt: string; + companyId: number; + contactListId: number; + tagListId: number | string; + fileListId: number; +}; + +type FindParams = { + companyId: string; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + const { companyId } = req.user; + + const { records, count, hasMore } = await ListService({ + searchParam, + pageNumber, + companyId + }); + + return res.json({ records, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + const data = req.body as StoreData; + console.log('data------- store:', data); + + const schema = Yup.object().shape({ + name: Yup.string().required() + }); + + try { + await schema.validate(data); + } catch (err: any) { + throw new AppError(err.message); + } + + if (typeof data.tagListId === 'number') { + + const tagId = data.tagListId; + const campanhaNome = data.name; + + async function createContactListFromTag(tagId) { + + const currentDate = new Date(); + const formattedDate = currentDate.toISOString(); + + try { + const ticketTags = await TicketTag.findAll({ where: { tagId } }); + const ticketIds = ticketTags.map((ticketTag) => ticketTag.ticketId); + + const tickets = await Ticket.findAll({ where: { id: ticketIds } }); + const contactIds = tickets.map((ticket) => ticket.contactId); + + const contacts = await Contact.findAll({ where: { id: contactIds } }); + + const randomName = `${campanhaNome} | TAG: ${tagId} - ${formattedDate}` // Implement your own function to generate a random name + const contactList = await ContactList.create({ name: randomName, companyId: companyId }); + + const { id: contactListId } = contactList; + + const contactListItems = contacts.map((contact) => ({ + name: contact.name, + number: contact.number, + email: contact.email, + contactListId, + companyId, + isWhatsappValid: true, + + })); + + await ContactListItem.bulkCreate(contactListItems); + + // Return the ContactList ID + return contactListId; + } catch (error) { + console.error('Error creating contact list:', error); + throw error; + } + } + + + createContactListFromTag(tagId) + .then(async (contactListId) => { + const record = await CreateService({ + ...data, + companyId, + contactListId: contactListId, + }); + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-campaign`, { + action: "create", + record + }); + return res.status(200).json(record); + }) + .catch((error) => { + console.error('Error:', error); + return res.status(500).json({ error: 'Error creating contact list' }); + }); + + } else { // SAI DO CHECK DE TAG + + + const record = await CreateService({ + ...data, + companyId + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-campaign`, { + action: "create", + record + }); + + return res.status(200).json(record); + } +}; + +export const show = async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const record = await ShowService(id); + + return res.status(200).json(record); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const data = req.body as StoreData; + const { companyId } = req.user; + + const schema = Yup.object().shape({ + name: Yup.string().required() + }); + + try { + await schema.validate(data); + } catch (err: any) { + throw new AppError(err.message); + } + + const { id } = req.params; + + const record = await UpdateService({ + ...data, + id + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-campaign`, { + action: "update", + record + }); + + return res.status(200).json(record); +}; + +export const cancel = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + + await CancelService(+id); + + return res.status(204).json({ message: "Cancelamento realizado" }); +}; + +export const restart = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + + await RestartService(+id); + + return res.status(204).json({ message: "Reinício dos disparos" }); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const { companyId } = req.user; + + await DeleteService(id); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-campaign`, { + action: "delete", + id + }); + + return res.status(200).json({ message: "Campaign deleted" }); +}; + +export const findList = async ( + req: Request, + res: Response +): Promise => { + const params = req.query as FindParams; + const records: Campaign[] = await FindService(params); + + return res.status(200).json(records); +}; + +export const mediaUpload = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const files = req.files as Express.Multer.File[]; + const file = head(files); + + try { + const campaign = await Campaign.findByPk(id); + campaign.mediaPath = file.filename; + campaign.mediaName = file.originalname; + await campaign.save(); + return res.send({ mensagem: "Mensagem enviada" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; + +export const deleteMedia = async ( + req: Request, + res: Response +): Promise => { + const { companyId } = req.user; + const { id } = req.params; + + try { + const campaign = await Campaign.findByPk(id); + const filePath = path.resolve("public", `company${companyId}`, campaign.mediaPath); + const fileExists = fs.existsSync(filePath); + if (fileExists) { + fs.unlinkSync(filePath); + } + + campaign.mediaPath = null; + campaign.mediaName = null; + await campaign.save(); + return res.send({ mensagem: "Arquivo excluído" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; diff --git a/backend/src/controllers/CampaignSettingController.ts b/backend/src/controllers/CampaignSettingController.ts new file mode 100644 index 0000000..860dfaf --- /dev/null +++ b/backend/src/controllers/CampaignSettingController.ts @@ -0,0 +1,34 @@ +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; + +import ListService from "../services/CampaignSettingServices/ListService"; +import CreateService from "../services/CampaignSettingServices/CreateService"; + +interface StoreData { + settings: any; +} + +export const index = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + + const records = await ListService({ + companyId + }); + + return res.json(records); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + const data = req.body as StoreData; + + const record = await CreateService(data, companyId); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-campaignSettings`, { + action: "create", + record + }); + + return res.status(200).json(record); +}; diff --git a/backend/src/controllers/ChannelHubController.ts b/backend/src/controllers/ChannelHubController.ts new file mode 100644 index 0000000..2ff8a8d --- /dev/null +++ b/backend/src/controllers/ChannelHubController.ts @@ -0,0 +1,38 @@ +import { Request, Response } from "express"; +import CreateChannelsService from "../services/HubServices/CreateHubChannelsService"; +import { setChannelWebhook } from "../helpers/setChannelHubWebhook"; +import { getIO } from "../libs/socket"; +import ListChannels from "../services/HubServices/ListHubChannels"; + +export interface IChannel { + name: string; + status?: string; + isDefault?: boolean; + qrcode?: string; + type?: string; + channel?: string; + id?:string; +} + +export const store = async (req: Request, res: Response): Promise => { + + const { whatsapps } = await CreateChannelsService(req.body); + + whatsapps.forEach(whatsapp => { + setTimeout(() => { + setChannelWebhook(whatsapp, whatsapp.id.toString()); + }, 2000); + }); + + return res.status(200).json(whatsapps); +}; + +export const index = async (req: Request, res: Response): Promise => { + + try { + const channels = await ListChannels(); + return res.status(200).json(channels); + } catch (error) { + return res.status(500).json({ error: error }); + } +}; \ No newline at end of file diff --git a/backend/src/controllers/ChatController.ts b/backend/src/controllers/ChatController.ts new file mode 100644 index 0000000..6165181 --- /dev/null +++ b/backend/src/controllers/ChatController.ts @@ -0,0 +1,205 @@ +import * as Yup from "yup"; +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; + +import CreateService from "../services/ChatService/CreateService"; +import ListService from "../services/ChatService/ListService"; +import ShowFromUuidService from "../services/ChatService/ShowFromUuidService"; +import DeleteService from "../services/ChatService/DeleteService"; +import FindMessages from "../services/ChatService/FindMessages"; +import UpdateService from "../services/ChatService/UpdateService"; + +import Chat from "../models/Chat"; +import CreateMessageService from "../services/ChatService/CreateMessageService"; +import User from "../models/User"; +import ChatUser from "../models/ChatUser"; + +type IndexQuery = { + pageNumber: string; + companyId: string | number; + ownerId?: number; +}; + +type StoreData = { + users: any[]; + title: string; +}; + +type FindParams = { + companyId: number; + ownerId?: number; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { pageNumber } = req.query as unknown as IndexQuery; + const ownerId = +req.user.id; + + const { records, count, hasMore } = await ListService({ + ownerId, + pageNumber + }); + + return res.json({ records, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + const ownerId = +req.user.id; + const data = req.body as StoreData; + + const record = await CreateService({ + ...data, + ownerId, + companyId + }); + + const io = getIO(); + + record.users.forEach(user => { + io.to(`user-${user.userId}`).emit(`company-${companyId}-chat-user-${user.userId}`, { + action: "create", + record + }); + }); + + return res.status(200).json(record); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const { companyId } = req.user; + const data = req.body; + const { id } = req.params; + + const record = await UpdateService({ + ...data, + id: +id + }); + + const io = getIO(); + + record.users.forEach(user => { + io.to(`user-${user.userId}`).emit(`company-${companyId}-chat-user-${user.userId}`, { + action: "update", + record + }); + }); + + return res.status(200).json(record); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const record = await ShowFromUuidService(id); + + return res.status(200).json(record); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const { companyId } = req.user; + + await DeleteService(id); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-chat`, { + action: "delete", + id + }); + + return res.status(200).json({ message: "Chat deleted" }); +}; + +export const saveMessage = async ( + req: Request, + res: Response +): Promise => { + const { companyId } = req.user; + const { message } = req.body; + const { id } = req.params; + const senderId = +req.user.id; + const chatId = +id; + + const newMessage = await CreateMessageService({ + chatId, + senderId, + message + }); + + const chat = await Chat.findByPk(chatId, { + include: [ + { model: User, as: "owner" }, + { model: ChatUser, as: "users" } + ] + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-chat-${chatId}`, { + action: "new-message", + newMessage, + chat + }); + + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-chat`, { + action: "new-message", + newMessage, + chat + }); + + return res.json(newMessage); +}; + +export const checkAsRead = async ( + req: Request, + res: Response +): Promise => { + const { companyId } = req.user; + const { userId } = req.body; + const { id } = req.params; + + const chatUser = await ChatUser.findOne({ where: { chatId: id, userId } }); + await chatUser.update({ unreads: 0 }); + + const chat = await Chat.findByPk(id, { + include: [ + { model: User, as: "owner" }, + { model: ChatUser, as: "users" } + ] + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-chat-${id}`, { + action: "update", + chat + }); + + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-chat`, { + action: "update", + chat + }); + + return res.json(chat); +}; + +export const messages = async ( + req: Request, + res: Response +): Promise => { + const { pageNumber } = req.query as unknown as IndexQuery; + const { id: chatId } = req.params; + const ownerId = +req.user.id; + + const { records, count, hasMore } = await FindMessages({ + chatId, + ownerId, + pageNumber + }); + + return res.json({ records, count, hasMore }); +}; diff --git a/backend/src/controllers/CompanyController.ts b/backend/src/controllers/CompanyController.ts new file mode 100644 index 0000000..8c66d43 --- /dev/null +++ b/backend/src/controllers/CompanyController.ts @@ -0,0 +1,200 @@ +import { Request, Response } from "express"; +import * as Yup from "yup"; +// import { getIO } from "../libs/socket"; +import authConfig from "../config/auth"; +import AppError from "../errors/AppError"; +import Company from "../models/Company"; +import fs from "fs"; +import path from "path"; +import { verify } from "jsonwebtoken"; +import User from "../models/User"; +import CreateCompanyService from "../services/CompanyService/CreateCompanyService"; +import DeleteCompanyService from "../services/CompanyService/DeleteCompanyService"; +import FindAllCompaniesService from "../services/CompanyService/FindAllCompaniesService"; +import ListCompaniesPlanService from "../services/CompanyService/ListCompaniesPlanService"; +import ListCompaniesService from "../services/CompanyService/ListCompaniesService"; +import ShowCompanyService from "../services/CompanyService/ShowCompanyService"; +import ShowPlanCompanyService from "../services/CompanyService/ShowPlanCompanyService"; +import UpdateCompanyService from "../services/CompanyService/UpdateCompanyService"; +import UpdateSchedulesService from "../services/CompanyService/UpdateSchedulesService"; + +const publicFolder = path.resolve(__dirname, "..", "..", "public"); + +type IndexQuery = { + searchParam: string; + pageNumber: string; +}; + +interface TokenPayload { + id: string; + username: string; + profile: string; + companyId: number; + iat: number; + exp: number; +} + +type CompanyData = { + name: string; + id?: number; + phone?: string; + email?: string; + status?: boolean; + planId?: number; + campaignsEnabled?: boolean; + dueDate?: string; + recurrence?: string; +}; + +type SchedulesData = { + schedules: []; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + + const { companies, count, hasMore } = await ListCompaniesService({ + searchParam, + pageNumber + }); + + return res.json({ companies, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const newCompany: CompanyData = req.body; + + const schema = Yup.object().shape({ + name: Yup.string().required() + }); + + try { + await schema.validate(newCompany); + } catch (err: any) { + throw new AppError(err.message); + } + + const company = await CreateCompanyService(newCompany); + + return res.status(200).json(company); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const company = await ShowCompanyService(id); + + return res.status(200).json(company); +}; + +export const list = async (req: Request, res: Response): Promise => { + const companies: Company[] = await FindAllCompaniesService(); + + return res.status(200).json(companies); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const companyData: CompanyData = req.body; + + const schema = Yup.object().shape({ + name: Yup.string() + }); + + try { + await schema.validate(companyData); + } catch (err: any) { + throw new AppError(err.message); + } + + const { id } = req.params; + + const company = await UpdateCompanyService({ id, ...companyData }); + + return res.status(200).json(company); +}; + +export const updateSchedules = async ( + req: Request, + res: Response +): Promise => { + const { schedules }: SchedulesData = req.body; + const { id } = req.params; + + const company = await UpdateSchedulesService({ + id, + schedules + }); + + return res.status(200).json(company); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const userId = req.user.id; + const requestUser = await User.findByPk(userId); + + if (requestUser.super === false) { + throw new AppError("você nao tem permissão para este consulta"); + } + const { id } = req.params; + + if (fs.existsSync(`${publicFolder}/company${id}/`)) { + + const removefolder = await fs.rmdirSync(`${publicFolder}/company${id}/`, { + recursive: true, + }); + + } + + const company = await DeleteCompanyService(id); + + + //fs.remove(`${publicFolder}/company${id}/`); + + return res.status(200).json(company); +}; + +export const listPlan = async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const authHeader = req.headers.authorization; + const [, token] = authHeader.split(" "); + const decoded = verify(token, authConfig.secret); + const { id: requestUserId, profile, companyId } = decoded as TokenPayload; + const requestUser = await User.findByPk(requestUserId); + + if (requestUser.super === true) { + const company = await ShowPlanCompanyService(id); + return res.status(200).json(company); + } else if (companyId.toString() !== id) { + return res.status(400).json({ error: "Você não possui permissão para acessar este recurso!" }); + } else { + const company = await ShowPlanCompanyService(id); + return res.status(200).json(company); + } + +}; + +export const indexPlan = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + + const authHeader = req.headers.authorization; + const [, token] = authHeader.split(" "); + const decoded = verify(token, authConfig.secret); + const { id, profile, companyId } = decoded as TokenPayload; + // const company = await Company.findByPk(companyId); + const requestUser = await User.findByPk(id); + + if (requestUser.super === true) { + const companies = await ListCompaniesPlanService(); + return res.json({ companies }); + } else { + return res.status(400).json({ error: "Você não possui permissão para acessar este recurso!" }); + } + +}; \ No newline at end of file diff --git a/backend/src/controllers/ContactController.ts b/backend/src/controllers/ContactController.ts new file mode 100644 index 0000000..d50c8cb --- /dev/null +++ b/backend/src/controllers/ContactController.ts @@ -0,0 +1,259 @@ +import * as Yup from "yup"; +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; + +import Contact from "../models/Contact"; +import ListContactsService from "../services/ContactServices/ListContactsService"; +import CreateContactService from "../services/ContactServices/CreateContactService"; +import ShowContactService from "../services/ContactServices/ShowContactService"; +import UpdateContactService from "../services/ContactServices/UpdateContactService"; +import DeleteContactService from "../services/ContactServices/DeleteContactService"; +import GetContactService from "../services/ContactServices/GetContactService"; + +import CheckContactNumber from "../services/WbotServices/CheckNumber"; +import CheckIsValidContact from "../services/WbotServices/CheckIsValidContact"; +import GetProfilePicUrl from "../services/WbotServices/GetProfilePicUrl"; +import AppError from "../errors/AppError"; +import SimpleListService, { + SearchContactParams +} from "../services/ContactServices/SimpleListService"; +import ContactCustomField from "../models/ContactCustomField"; +import {head} from "lodash"; +import {ImportContacts} from "../services/ContactServices/ImportContacts"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; +}; + +type IndexGetContactQuery = { + name: string; + number: string; +}; + +interface ExtraInfo extends ContactCustomField { + name: string; + value: string; +} +interface ContactData { + name: string; + number: string; + email?: string; + extraInfo?: ExtraInfo[]; +} + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + const { companyId } = req.user; + + const { contacts, count, hasMore } = await ListContactsService({ + searchParam, + pageNumber, + companyId + }); + + return res.json({ contacts, count, hasMore }); +}; + +export const getContact = async ( + req: Request, + res: Response +): Promise => { + const { name, number } = req.body as IndexGetContactQuery; + const { companyId } = req.user; + + const contact = await GetContactService({ + name, + number, + companyId + }); + + return res.status(200).json(contact); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + const newContact: ContactData = req.body; + newContact.number = newContact.number.replace("-", "").replace(" ", ""); + + const schema = Yup.object().shape({ + name: Yup.string().required(), + /*number: Yup.string() + .required() + .matches(/^\d+$/, "Invalid number format. Only numbers is allowed.")*/ + }); + + try { + await schema.validate(newContact); + } catch (err: any) { + throw new AppError(err.message); + } + + await CheckIsValidContact(newContact.number, companyId); + const validNumber = await CheckContactNumber(newContact.number, companyId); + const number = validNumber.jid.replace(/\D/g, ""); + newContact.number = number; + + // Check if the contact already exists + const existingContact = await Contact.findOne({ + where: { + number: newContact.number, + companyId + } + }); + + if (existingContact) { + // Contact already exists, send the existing contact data as the response + return res.status(200).json({ alreadyExists: true, existingContact }); + } + + /** + * Código desabilitado por demora no retorno + */ + // const profilePicUrl = await GetProfilePicUrl(validNumber.jid, companyId); + + const contact = await CreateContactService({ + ...newContact, + // profilePicUrl, + companyId + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-contact`, { + action: "create", + contact + }); + + return res.status(200).json(contact); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { contactId } = req.params; + const { companyId } = req.user; + + const contact = await ShowContactService(contactId, companyId); + + return res.status(200).json(contact); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const contactData: ContactData = req.body; + const { companyId } = req.user; + + const schema = Yup.object().shape({ + name: Yup.string(), + /*number: Yup.string().matches( + /^\d+$/, + "Invalid number format. Only numbers is allowed." + )*/ + }); + + try { + await schema.validate(contactData); + } catch (err: any) { + throw new AppError(err.message); + } + + /*await CheckIsValidContact(contactData.number, companyId); + const validNumber = await CheckContactNumber(contactData.number, companyId); + const number = validNumber.jid.replace(/\D/g, ""); + contactData.number = number; +*/ + const { contactId } = req.params; + + const contact = await UpdateContactService({ + contactData, + contactId, + companyId + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-contact`, { + action: "update", + contact + }); + + return res.status(200).json(contact); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { contactId } = req.params; + const { companyId } = req.user; + + await ShowContactService(contactId, companyId); + + await DeleteContactService(contactId); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-contact`, { + action: "delete", + contactId + }); + + return res.status(200).json({ message: "Contact deleted" }); +}; + +export const list = async (req: Request, res: Response): Promise => { + const { name } = req.query as unknown as SearchContactParams; + const { companyId } = req.user; + + const contacts = await SimpleListService({ name, companyId }); + + return res.json(contacts); +}; + +export const upload = async (req: Request, res: Response) => { + const files = req.files as Express.Multer.File[]; + const file: Express.Multer.File = head(files) as Express.Multer.File; + const { companyId } = req.user; + + const response = await ImportContacts(companyId, file); + + const io = getIO(); + + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-contact`, { + action: "create", + records: response + }); + + return res.status(200).json(response); +}; + +export const getContactVcard = async ( + req: Request, + res: Response +): Promise => { + const { name, number } = req.query as IndexGetContactQuery; + const { companyId } = req.user; + + let vNumber = number; + const numberDDI = vNumber.toString().substr(0, 2); + const numberDDD = vNumber.toString().substr(2, 2); + const numberUser = vNumber.toString().substr(-8, 8); + + if (numberDDD <= '30' && numberDDI === '55') { + console.log("menor 30") + vNumber = `${numberDDI + numberDDD + 9 + numberUser}@s.whatsapp.net`; + } else if (numberDDD > '30' && numberDDI === '55') { + console.log("maior 30") + vNumber = `${numberDDI + numberDDD + numberUser}@s.whatsapp.net`; + } else { + vNumber = `${number}@s.whatsapp.net`; + } + + console.log(vNumber); + + const contact = await GetContactService({ + name, + number, + companyId + }); + + return res.status(200).json(contact); +}; \ No newline at end of file diff --git a/backend/src/controllers/ContactListController.ts b/backend/src/controllers/ContactListController.ts new file mode 100644 index 0000000..ba1b422 --- /dev/null +++ b/backend/src/controllers/ContactListController.ts @@ -0,0 +1,159 @@ +import * as Yup from "yup"; +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; + +import ListService from "../services/ContactListService/ListService"; +import CreateService from "../services/ContactListService/CreateService"; +import ShowService from "../services/ContactListService/ShowService"; +import UpdateService from "../services/ContactListService/UpdateService"; +import DeleteService from "../services/ContactListService/DeleteService"; +import FindService from "../services/ContactListService/FindService"; +import { head } from "lodash"; + +import ContactList from "../models/ContactList"; + +import AppError from "../errors/AppError"; +import { ImportContacts } from "../services/ContactListService/ImportContacts"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; + companyId: string | number; +}; + +type StoreData = { + name: string; + companyId: string; +}; + +type FindParams = { + companyId: string; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + const { companyId } = req.user; + + const { records, count, hasMore } = await ListService({ + searchParam, + pageNumber, + companyId + }); + + return res.json({ records, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + const data = req.body as StoreData; + + const schema = Yup.object().shape({ + name: Yup.string().required() + }); + + try { + await schema.validate(data); + } catch (err: any) { + throw new AppError(err.message); + } + + const record = await CreateService({ + ...data, + companyId + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-ContactList`, { + action: "create", + record + }); + + return res.status(200).json(record); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const record = await ShowService(id); + + return res.status(200).json(record); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const data = req.body as StoreData; + const { companyId } = req.user; + + const schema = Yup.object().shape({ + name: Yup.string().required() + }); + + try { + await schema.validate(data); + } catch (err: any) { + throw new AppError(err.message); + } + + const { id } = req.params; + + const record = await UpdateService({ + ...data, + id + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-ContactList`, { + action: "update", + record + }); + + return res.status(200).json(record); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const { companyId } = req.user; + + await DeleteService(id); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-ContactList`, { + action: "delete", + id + }); + + return res.status(200).json({ message: "Contact list deleted" }); +}; + +export const findList = async ( + req: Request, + res: Response +): Promise => { + const params = req.query as FindParams; + const records: ContactList[] = await FindService(params); + + return res.status(200).json(records); +}; + +export const upload = async (req: Request, res: Response) => { + const files = req.files as Express.Multer.File[]; + const file: Express.Multer.File = head(files) as Express.Multer.File; + const { id } = req.params; + const { companyId } = req.user; + + const response = await ImportContacts(+id, companyId, file); + + const io = getIO(); + + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-ContactListItem-${+id}`, { + action: "reload", + records: response + }); + + return res.status(200).json(response); +}; diff --git a/backend/src/controllers/ContactListItemController.ts b/backend/src/controllers/ContactListItemController.ts new file mode 100644 index 0000000..56295be --- /dev/null +++ b/backend/src/controllers/ContactListItemController.ts @@ -0,0 +1,145 @@ +import * as Yup from "yup"; +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; + +import ListService from "../services/ContactListItemService/ListService"; +import CreateService from "../services/ContactListItemService/CreateService"; +import ShowService from "../services/ContactListItemService/ShowService"; +import UpdateService from "../services/ContactListItemService/UpdateService"; +import DeleteService from "../services/ContactListItemService/DeleteService"; +import FindService from "../services/ContactListItemService/FindService"; + +import ContactListItem from "../models/ContactListItem"; + +import AppError from "../errors/AppError"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; + companyId: string | number; + contactListId: string | number; +}; + +type StoreData = { + name: string; + number: string; + contactListId: number; + companyId?: string; + email?: string; +}; + +type FindParams = { + companyId: number; + contactListId: number; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber, contactListId } = req.query as IndexQuery; + const { companyId } = req.user; + + const { contacts, count, hasMore } = await ListService({ + searchParam, + pageNumber, + companyId, + contactListId + }); + + return res.json({ contacts, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + const data = req.body as StoreData; + + const schema = Yup.object().shape({ + name: Yup.string().required() + }); + + try { + await schema.validate(data); + } catch (err: any) { + throw new AppError(err.message); + } + + const record = await CreateService({ + ...data, + companyId + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-ContactListItem`, { + action: "create", + record + }); + + return res.status(200).json(record); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const record = await ShowService(id); + + return res.status(200).json(record); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const data = req.body as StoreData; + const { companyId } = req.user; + + const schema = Yup.object().shape({ + name: Yup.string().required() + }); + + try { + await schema.validate(data); + } catch (err: any) { + throw new AppError(err.message); + } + + const { id } = req.params; + + const record = await UpdateService({ + ...data, + id + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-ContactListItem`, { + action: "update", + record + }); + + return res.status(200).json(record); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const { companyId } = req.user; + + await DeleteService(id); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-ContactListItem`, { + action: "delete", + id + }); + + return res.status(200).json({ message: "Contact deleted" }); +}; + +export const findList = async ( + req: Request, + res: Response +): Promise => { + const params = req.query as unknown as FindParams; + const records: ContactListItem[] = await FindService(params); + + return res.status(200).json(records); +}; diff --git a/backend/src/controllers/DashbardController.ts b/backend/src/controllers/DashbardController.ts new file mode 100644 index 0000000..4607478 --- /dev/null +++ b/backend/src/controllers/DashbardController.ts @@ -0,0 +1,55 @@ +import { Request, Response } from 'express'; +import DashboardDataService, { + DashboardData, + Params, +} from '../services/ReportService/DashbardDataService'; +import { TicketsAttendance } from '../services/ReportService/TicketsAttendance'; +import { TicketsDayService } from '../services/ReportService/TicketsDayService'; + +type IndexQuery = { + initialDate: string; + finalDate: string; + companyId: number | any; +}; + +export const index = async (req: Request, res: Response): Promise => { + const params: Params = req.query; + const { companyId } = req.user; + let daysInterval = 3; + + const dashboardData: DashboardData = await DashboardDataService( + companyId, + params, + ); + return res.status(200).json(dashboardData); +}; + +export const reportsUsers = async ( + req: Request, + res: Response, +): Promise => { + const { initialDate, finalDate, companyId } = req.query as IndexQuery; + + const { data } = await TicketsAttendance({ + initialDate, + finalDate, + companyId, + }); + + return res.json({ data }); +}; + +export const reportsDay = async ( + req: Request, + res: Response, +): Promise => { + const { initialDate, finalDate, companyId } = req.query as IndexQuery; + + const { count, data } = await TicketsDayService({ + initialDate, + finalDate, + companyId, + }); + + return res.json({ count, data }); +}; diff --git a/backend/src/controllers/FilesController.ts b/backend/src/controllers/FilesController.ts new file mode 100644 index 0000000..ee54e26 --- /dev/null +++ b/backend/src/controllers/FilesController.ts @@ -0,0 +1,155 @@ +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; + +import AppError from "../errors/AppError"; +import { head } from "lodash"; + +import CreateService from "../services/FileServices/CreateService"; +import ListService from "../services/FileServices/ListService"; +import UpdateService from "../services/FileServices/UpdateService"; +import ShowService from "../services/FileServices/ShowService"; +import DeleteService from "../services/FileServices/DeleteService"; +import SimpleListService from "../services/FileServices/SimpleListService"; +import DeleteAllService from "../services/FileServices/DeleteAllService"; +import ShowTicketService from "../services/TicketServices/ShowTicketService"; +import UpdateTicketService from "../services/TicketServices/UpdateTicketService"; +import FilesOptions from "../models/FilesOptions"; + +type IndexQuery = { + searchParam?: string; + pageNumber?: string | number; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { pageNumber, searchParam } = req.query as IndexQuery; + const { companyId } = req.user; + + const { files, count, hasMore } = await ListService({ + searchParam, + pageNumber, + companyId + }); + + return res.json({ files, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { name, message, options } = req.body; + const { companyId } = req.user; + + const fileList = await CreateService({ + name, + message, + options, + companyId + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company${companyId}-file`, { + action: "create", + fileList + }); + + return res.status(200).json(fileList); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { fileId } = req.params; + const { companyId } = req.user; + + const file = await ShowService(fileId, companyId); + + return res.status(200).json(file); +}; + +export const uploadMedias = async (req: Request, res: Response): Promise => { + const { fileId, id, mediaType } = req.body; + const files = req.files as Express.Multer.File[]; + const file = head(files); + + try { + + let fileOpt + if (files.length > 0) { + + for (const [index, file] of files.entries()) { + fileOpt = await FilesOptions.findOne({ + where: { + fileId, + id: Array.isArray(id)? id[index] : id + } + }); + + fileOpt.update({ + path: file.filename.replace('/','-'), + mediaType: Array.isArray(mediaType)? mediaType[index] : mediaType + }) ; + } + } + + return res.send({ mensagem: "Arquivos atualizados" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + if (req.user.profile !== "admin") { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + const { fileId } = req.params; + const fileData = req.body; + const { companyId } = req.user; + + const fileList = await UpdateService({ fileData, id: fileId, companyId }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company${companyId}-file`, { + action: "update", + fileList + }); + + return res.status(200).json(fileList); +}; + + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { fileId } = req.params; + const { companyId } = req.user; + + await DeleteService(fileId, companyId); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company${companyId}-file`, { + action: "delete", + fileId + }); + + return res.status(200).json({ message: "File List deleted" }); +}; + +export const removeAll = async ( + req: Request, + res: Response +): Promise => { + const { companyId } = req.user; + await DeleteAllService(companyId); + + return res.send(); +}; + +export const list = async (req: Request, res: Response): Promise => { + const { searchParam } = req.query as IndexQuery; + const { companyId } = req.user; + + const ratings = await SimpleListService({ searchParam, companyId }); + + return res.json(ratings); +}; diff --git a/backend/src/controllers/ForgotController.ts b/backend/src/controllers/ForgotController.ts new file mode 100644 index 0000000..121efb2 --- /dev/null +++ b/backend/src/controllers/ForgotController.ts @@ -0,0 +1,25 @@ +import { v4 as uuid } from "uuid"; +import { Request, Response } from "express"; +import SendMail from "../services/ForgotPassWordServices/SendMail"; +import ResetPassword from "../services/ResetPasswordService/ResetPassword"; +type IndexQuery = { email?: string; token?: string; password?: string }; +export const store = async (req: Request, res: Response): Promise => { + const { email } = req.params as IndexQuery; + const TokenSenha = uuid(); + const forgotPassword = await SendMail(email, TokenSenha); + if (!forgotPassword) { + return res.status(200).json({ message: "E-mail enviado com sucesso" }); + } + return res.status(404).json({ error: "E-mail enviado com sucesso" }); +}; +export const resetPasswords = async ( + req: Request, + res: Response +): Promise => { + const { email, token, password } = req.params as IndexQuery; + const resetPassword = await ResetPassword(email, token, password); + if (!resetPassword) { + return res.status(200).json({ message: "Senha redefinida com sucesso" }); + } + return res.status(404).json({ error: "Verifique o Token informado" }); +}; diff --git a/backend/src/controllers/HelpController.ts b/backend/src/controllers/HelpController.ts new file mode 100644 index 0000000..e6bb521 --- /dev/null +++ b/backend/src/controllers/HelpController.ts @@ -0,0 +1,131 @@ +import * as Yup from "yup"; +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; + +import ListService from "../services/HelpServices/ListService"; +import CreateService from "../services/HelpServices/CreateService"; +import ShowService from "../services/HelpServices/ShowService"; +import UpdateService from "../services/HelpServices/UpdateService"; +import DeleteService from "../services/HelpServices/DeleteService"; +import FindService from "../services/HelpServices/FindService"; + +import Help from "../models/Help"; + +import AppError from "../errors/AppError"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; +}; + +type StoreData = { + title: string; + description: string; + video?: string; + link?: string; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + + const { records, count, hasMore } = await ListService({ + searchParam, + pageNumber + }); + return res.json({ records, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + const data = req.body as StoreData; + + const schema = Yup.object().shape({ + title: Yup.string().required() + }); + + try { + await schema.validate(data); + } catch (err) { + throw new AppError(err.message); + } + + const record = await CreateService({ + ...data + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-help`, { + action: "create", + record + }); + + return res.status(200).json(record); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const record = await ShowService(id); + + return res.status(200).json(record); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const data = req.body as StoreData; + const { companyId } = req.user; + + const schema = Yup.object().shape({ + title: Yup.string().required() + }); + + try { + await schema.validate(data); + } catch (err) { + throw new AppError(err.message); + } + + const { id } = req.params; + + const record = await UpdateService({ + ...data, + id + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-help`, { + action: "update", + record + }); + + return res.status(200).json(record); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const { companyId } = req.user; + + await DeleteService(id); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-help`, { + action: "delete", + id + }); + + return res.status(200).json({ message: "Help deleted" }); +}; + +export const findList = async ( + req: Request, + res: Response +): Promise => { + const records: Help[] = await FindService(); + + return res.status(200).json(records); +}; diff --git a/backend/src/controllers/HubNotificaMeController.ts b/backend/src/controllers/HubNotificaMeController.ts new file mode 100644 index 0000000..dc931a2 --- /dev/null +++ b/backend/src/controllers/HubNotificaMeController.ts @@ -0,0 +1,148 @@ +import * as Yup from "yup"; +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; + +import ListService from "../services/HubNotificaMeService/ListService"; +import CreateService from "../services/HubNotificaMeService/CreateService"; +import ShowService from "../services/HubNotificaMeService/ShowService"; +import UpdateService from "../services/HubNotificaMeService/UpdateService"; +import DeleteService from "../services/HubNotificaMeService/DeleteService"; +import FindService from "../services/HubNotificaMeService/FindService"; + +import HubNotificaMe from "../models/HubNotificaMe"; + +import { head } from "lodash"; +import fs from "fs"; +import path from "path"; + +import AppError from "../errors/AppError"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; +}; + +type StoreData = { + nome: string; + token: string; + tipo: string; +}; + +type FindParams = { + companyId: string; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + const { companyId } = req.user; + + const { records, count, hasMore } = await ListService({ + searchParam, + pageNumber, + companyId + }); + + return res.json({ records, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + const data = req.body as StoreData; + + // Certifique-se de que o tipo foi fornecido + const schema = Yup.object().shape({ + nome: Yup.string().required(), + token: Yup.string().required(), + tipo: Yup.string().oneOf(["Facebook", "Instagram"], "Tipo inválido").required("Tipo é obrigatório"), // Validação do tipo + }); + + try { + await schema.validate(data); + } catch (err: any) { + throw new AppError(err.message); + } + + const record = await CreateService({ + ...data, + companyId + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-hubnotificame`, { + action: "create", + record + }); + + return res.status(200).json(record); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const record = await ShowService(id); + + return res.status(200).json(record); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const data = req.body as StoreData; + const { companyId } = req.user; + + const schema = Yup.object().shape({ + nome: Yup.string().required(), + token: Yup.string().required(), + tipo: Yup.string().oneOf(["Facebook", "Instagram"], "Tipo inválido").required("Tipo é obrigatório"), // Validação do tipo + }); + + try { + await schema.validate(data); + } catch (err: any) { + throw new AppError(err.message); + } + + const { id } = req.params; + + const record = await UpdateService({ + ...data, + id, + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-hubnotificame`, { + action: "update", + record + }); + + return res.status(200).json(record); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const { companyId } = req.user; + + await DeleteService(id); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-hubnotificame`, { + action: "delete", + id + }); + + return res.status(200).json({ message: "Contact deleted" }); +}; + +export const findList = async ( + req: Request, + res: Response +): Promise => { + const params = req.query as FindParams; + const records: HubNotificaMe[] = await FindService(params); + + return res.status(200).json(records); +}; diff --git a/backend/src/controllers/ImportPhoneContactsController.ts b/backend/src/controllers/ImportPhoneContactsController.ts new file mode 100644 index 0000000..a1084f6 --- /dev/null +++ b/backend/src/controllers/ImportPhoneContactsController.ts @@ -0,0 +1,10 @@ +import { Request, Response } from "express"; +import ImportContactsService from "../services/WbotServices/ImportContactsService"; + +export const store = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + + await ImportContactsService(companyId); + + return res.status(200).json({ message: "contacts imported" }); +}; diff --git a/backend/src/controllers/InvoicesController.ts b/backend/src/controllers/InvoicesController.ts new file mode 100644 index 0000000..44180c8 --- /dev/null +++ b/backend/src/controllers/InvoicesController.ts @@ -0,0 +1,172 @@ +import * as Yup from "yup"; +import { Request, Response } from "express"; +// import { getIO } from "../libs/socket"; +import AppError from "../errors/AppError"; +import Invoices from "../models/Invoices"; + +import CreatePlanService from "../services/PlanService/CreatePlanService"; +import UpdatePlanService from "../services/PlanService/UpdatePlanService"; +import ShowPlanService from "../services/PlanService/ShowPlanService"; +import DeletePlanService from "../services/PlanService/DeletePlanService"; + +import FindAllInvoiceService from "../services/InvoicesService/FindAllInvoiceService"; +import ListInvoicesServices from "../services/InvoicesService/ListInvoicesServices"; +import ShowInvoceService from "../services/InvoicesService/ShowInvoiceService"; +import UpdateInvoiceService from "../services/InvoicesService/UpdateInvoiceService"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; +}; + +type StorePlanData = { + name: string; + id?: number | string; + users: number | 0; + connections: number | 0; + queues: number | 0; + value: number; +}; + +type UpdateInvoiceData = { + status: string; + id?: string; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + + const { invoices, count, hasMore } = await ListInvoicesServices({ + searchParam, + pageNumber + }); + + return res.json({ invoices, count, hasMore }); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { Invoiceid } = req.params; + + const invoice = await ShowInvoceService(Invoiceid); + + return res.status(200).json(invoice); +}; + + +export const list = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + const invoice: Invoices[] = await FindAllInvoiceService(companyId); + + return res.status(200).json(invoice); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const InvoiceData: UpdateInvoiceData = req.body; + + const schema = Yup.object().shape({ + name: Yup.string() + }); + + try { + await schema.validate(InvoiceData); + } catch (err) { + throw new AppError(err.message); + } + + const { id, status } = InvoiceData; + + const plan = await UpdateInvoiceService({ + id, + status, + + }); + + // const io = getIO(); + // io.emit("plan", { + // action: "update", + // plan + // }); + + return res.status(200).json(plan); +}; +/* export const store = async (req: Request, res: Response): Promise => { + const newPlan: StorePlanData = req.body; + + const schema = Yup.object().shape({ + name: Yup.string().required() + }); + + try { + await schema.validate(newPlan); + } catch (err) { + throw new AppError(err.message); + } + + const plan = await CreatePlanService(newPlan); + + // const io = getIO(); + // io.emit("plan", { + // action: "create", + // plan + // }); + + return res.status(200).json(plan); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const plan = await ShowPlanService(id); + + return res.status(200).json(plan); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const planData: UpdateInvoiceData = req.body; + + const schema = Yup.object().shape({ + name: Yup.string() + }); + + try { + await schema.validate(planData); + } catch (err) { + throw new AppError(err.message); + } + + const { id, name, users, connections, queues, value } = planData; + + const plan = await UpdatePlanService({ + id, + name, + users, + connections, + queues, + value + }); + + // const io = getIO(); + // io.emit("plan", { + // action: "update", + // plan + // }); + + return res.status(200).json(plan); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + + const plan = await DeletePlanService(id); + + return res.status(200).json(plan); +}; */ diff --git a/backend/src/controllers/MessageController.ts b/backend/src/controllers/MessageController.ts new file mode 100644 index 0000000..d45206f --- /dev/null +++ b/backend/src/controllers/MessageController.ts @@ -0,0 +1,370 @@ +import { Request, Response } from "express"; +import AppError from "../errors/AppError"; + +import formatBody from "../helpers/Mustache"; +import SetTicketMessagesAsRead from "../helpers/SetTicketMessagesAsRead"; +import { getIO } from "../libs/socket"; +import Ticket from "../models/Ticket"; +import Message from "../models/Message"; +import Queue from "../models/Queue"; +import User from "../models/User"; +import Whatsapp from "../models/Whatsapp"; +import { lookup } from 'mime-types'; +import { isNil } from "lodash"; +import QuickMessage from "../models/QuickMessage"; +import CreateOrUpdateContactService from "../services/ContactServices/CreateOrUpdateContactService"; +import SendWhatsAppReaction from "../services/WbotServices/SendWhatsAppReaction"; +import ListMessagesService from "../services/MessageServices/ListMessagesService"; +import FindOrCreateTicketService from "../services/TicketServices/FindOrCreateTicketService"; +import ShowTicketService from "../services/TicketServices/ShowTicketService"; +import UpdateTicketService from "../services/TicketServices/UpdateTicketService"; +import CheckContactNumber from "../services/WbotServices/CheckNumber"; +import DeleteWhatsAppMessage from "../services/WbotServices/DeleteWhatsAppMessage"; +import GetProfilePicUrl from "../services/WbotServices/GetProfilePicUrl"; +import ShowContactService from "../services/ContactServices/ShowContactService"; +import SendWhatsAppMedia from "../services/WbotServices/SendWhatsAppMedia"; +//import SendWhatsAppMediaInternal from "../services/WbotServices/SendWhatsAppMediaInternal"; +import path from "path"; +import SendWhatsAppMessage from "../services/WbotServices/SendWhatsAppMessage"; +import EditWhatsAppMessage from "../services/WbotServices/EditWhatsAppMessage"; +import ShowMessageService, { GetWhatsAppFromMessage } from "../services/MessageServices/ShowMessageService"; +type IndexQuery = { + pageNumber: string; +}; + +type MessageData = { + body: string; + fromMe: boolean; + read: boolean; + quotedMsg?: Message; + number?: string; + closeTicket?: true; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { ticketId } = req.params; + const { pageNumber } = req.query as IndexQuery; + const { companyId, profile } = req.user; + const queues: number[] = []; + + if (profile !== "admin") { + const user = await User.findByPk(req.user.id, { + include: [{ model: Queue, as: "queues" }] + }); + user.queues.forEach(queue => { + queues.push(queue.id); + }); + } + + const { count, messages, ticket, hasMore } = await ListMessagesService({ + pageNumber, + ticketId, + companyId, + queues + }); + + SetTicketMessagesAsRead(ticket); + + return res.json({ count, messages, ticket, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { ticketId } = req.params; + const { body, quotedMsg }: MessageData = req.body; + const medias = req.files as Express.Multer.File[]; + const { companyId } = req.user; + + const ticket = await ShowTicketService(ticketId, companyId); + + SetTicketMessagesAsRead(ticket); + + console.log('bodyyyyyyyyyy:', body) + if (medias) { + await Promise.all( + medias.map(async (media: Express.Multer.File, index) => { + await SendWhatsAppMedia({ media, ticket, body: Array.isArray(body) ? body[index] : body }); + }) + ); + } else { + const send = await SendWhatsAppMessage({ body, ticket, quotedMsg }); + } + + return res.send(); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { messageId } = req.params; + const { companyId } = req.user; + + const message = await DeleteWhatsAppMessage(messageId); + + const io = getIO(); + io.to(message.ticketId.toString()).emit(`company-${companyId}-appMessage`, { + action: "update", + message + }); + + return res.send(); +}; + +export const send = async (req: Request, res: Response): Promise => { + const { whatsappId } = req.params as unknown as { whatsappId: number }; + const messageData: MessageData = req.body; + const medias = req.files as Express.Multer.File[]; + + console.log('messageData;', messageData) + + try { + const whatsapp = await Whatsapp.findByPk(whatsappId); + + if (!whatsapp) { + throw new Error("Não foi possível realizar a operação"); + } + + if (messageData.number === undefined) { + throw new Error("O número é obrigatório"); + } + + const numberToTest = messageData.number; + const body = messageData.body; + + const companyId = whatsapp.companyId; + + const CheckValidNumber = await CheckContactNumber(numberToTest, companyId); + const number = CheckValidNumber.jid.replace(/\D/g, ""); + const profilePicUrl = await GetProfilePicUrl( + number, + companyId + ); + const contactData = { + name: `${number}`, + number, + profilePicUrl, + isGroup: false, + companyId + }; + + const contact = await CreateOrUpdateContactService(contactData); + + const ticket = await FindOrCreateTicketService(contact, whatsapp.id!, 0, companyId); + + if (medias) { + await Promise.all( + medias.map(async (media: Express.Multer.File) => { + await req.app.get("queues").messageQueue.add( + "SendMessage", + { + whatsappId, + data: { + number, + body: body ? formatBody(body, contact) : media.originalname, + mediaPath: media.path, + fileName: media.originalname + } + }, + { removeOnComplete: true, attempts: 3 } + ); + }) + ); + } else { + await SendWhatsAppMessage({ body: formatBody(body, contact), ticket }); + + await ticket.update({ + lastMessage: body, + }); + + } + + if (messageData.closeTicket) { + setTimeout(async () => { + await UpdateTicketService({ + ticketId: ticket.id, + ticketData: { status: "closed" }, + companyId + }); + }, 1000); + } + + SetTicketMessagesAsRead(ticket); + + return res.send({ mensagem: "Mensagem enviada" }); + } catch (err: any) { + if (Object.keys(err).length === 0) { + throw new AppError( + "Não foi possível enviar a mensagem, tente novamente em alguns instantes" + ); + } else { + throw new AppError(err.message); + } + } +}; + +export const addReaction = async (req: Request, res: Response): Promise => { + try { + const {messageId} = req.params; + const {type} = req.body; // O tipo de reação, por exemplo, 'like', 'heart', etc. + const {companyId, id} = req.user; + + const message = await Message.findByPk(messageId); + + const ticket = await Ticket.findByPk(message.ticketId, { + include: ["contact"] + }); + + if (!message) { + return res.status(404).send({message: "Mensagem não encontrada"}); + } + + // Envia a reação via WhatsApp + const reactionResult = await SendWhatsAppReaction({ + messageId: messageId, + ticket: ticket, + reactionType: type + }); + + // Atualiza a mensagem com a nova reação no banco de dados (opcional, dependendo da necessidade) + const updatedMessage = await message.update({ + reactions: [...message.reactions, {type: type, userId: id}] + }); + + const io = getIO(); + io.to(message.ticketId.toString()).emit(`company-${companyId}-appMessage`, { + action: "update", + message + }); + + return res.status(200).send({ + message: 'Reação adicionada com sucesso!', + reactionResult, + reactions: updatedMessage.reactions + }); + } catch (error) { + console.error('Erro ao adicionar reação:', error); + if (error instanceof AppError) { + return res.status(400).send({message: error.message}); + } + return res.status(500).send({message: 'Erro ao adicionar reação', error: error.message}); + } +}; + +function obterNomeEExtensaoDoArquivo(url) { + var urlObj = new URL(url); + var pathname = urlObj.pathname; + var filename = pathname.split('/').pop(); + var parts = filename.split('.'); + + var nomeDoArquivo = parts[0]; + var extensao = parts[1]; + + return `${nomeDoArquivo}.${extensao}`; +} + +export const forwardMessage = async ( + req: Request, + res: Response +): Promise => { + + const { quotedMsg, signMessage, messageId, contactId } = req.body; + const { id: userId, companyId } = req.user; + const requestUser = await User.findByPk(userId); + + if (!messageId || !contactId) { + return res.status(200).send("MessageId or ContactId not found"); + } + const message = await ShowMessageService(messageId); + const contact = await ShowContactService(contactId, companyId); + + if (!message) { + return res.status(404).send("Message not found"); + } + if (!contact) { + return res.status(404).send("Contact not found"); + } + + const whatsAppConnectionId = await GetWhatsAppFromMessage(message); + if (!whatsAppConnectionId) { + return res.status(404).send('Whatsapp from message not found'); + } + + const ticket = await ShowTicketService(message.ticketId, message.companyId); + + const createTicket = await FindOrCreateTicketService( + contact, + ticket?.whatsappId, + 0, + ticket.companyId, + contact.isGroup ? contact : null, + ); + + let ticketData; + + if (isNil(createTicket?.queueId)) { + ticketData = { + status: createTicket.isGroup ? "group" : "open", + userId: requestUser.id, + queueId: ticket.queueId + } + } else { + ticketData = { + status: createTicket.isGroup ? "group" : "open", + userId: requestUser.id + } + } + + await UpdateTicketService({ + ticketData, + ticketId: createTicket.id, + companyId: createTicket.companyId + }); + + let body = message.body; + if (message.mediaType === 'conversation' || message.mediaType === 'extendedTextMessage') { + await SendWhatsAppMessage({ body, ticket: createTicket, quotedMsg, isForwarded: message.fromMe ? false : true }); + } else { + + const mediaUrl = message.mediaUrl.replace(`:${process.env.PORT}`, ''); + const fileName = obterNomeEExtensaoDoArquivo(mediaUrl); + + if (body === fileName) { + body = ""; + } + + const publicFolder = path.join(__dirname, '..', '..', '..', 'backend', 'public'); + + const filePath = path.join(publicFolder, `company${createTicket.companyId}`, fileName) + + const mediaSrc = { + fieldname: 'medias', + originalname: fileName, + encoding: '7bit', + mimetype: message.mediaType, + filename: fileName, + path: filePath + } as Express.Multer.File + + await SendWhatsAppMedia({ media: mediaSrc, ticket: createTicket, body, isForwarded: message.fromMe ? false : true }); + } + + return res.send(); +} + +export const edit = async (req: Request, res: Response): Promise => { + const { messageId } = req.params; + const { companyId } = req.user; + const { body }: MessageData = req.body; + console.log(body) + const { ticket , message } = await EditWhatsAppMessage({messageId, body}); + + const io = getIO(); + io.emit(`company-${companyId}-appMessage`, { + action:"update", + message, + ticket: ticket, + contact: ticket.contact, + }); + + return res.send(); +} \ No newline at end of file diff --git a/backend/src/controllers/MessageHubController.ts b/backend/src/controllers/MessageHubController.ts new file mode 100644 index 0000000..36f993e --- /dev/null +++ b/backend/src/controllers/MessageHubController.ts @@ -0,0 +1,105 @@ +import { Request, Response } from "express"; +import User from "../models/User"; +import { getIO } from "../libs/socket"; +import Contact from "../models/Contact"; +import Ticket from "../models/Ticket"; +import Whatsapp from "../models/Whatsapp"; +import { SendMediaMessageService } from "../services/HubServices/SendMediaMessageHubService"; +import { SendTextMessageService } from "../services/HubServices/SendTextMessageHubService"; +import CreateHubTicketService from "../services/HubServices/CreateHubTicketService"; + + +interface TicketData { + contactId: number; + status: string; + queueId: number; + userId: number; + channel: string; + companyId: number; +} + +export const send = async (req: Request, res: Response): Promise => { + + const { companyId } = req.user; + + console.log('CompanyId do usuário autenticado:', companyId); // Verifique se companyId está correto aqui + + const { body: message } = req.body; + const { ticketId } = req.params; + const medias = req.files as Express.Multer.File[]; + + console.log("sending hub message controller"); + + const ticket = await Ticket.findOne({ + where: { id: ticketId, companyId }, // Filtro pelo companyId + include: [ + { + model: Contact, + as: "contact", + attributes: ["number", "messengerId", "instagramId"] + }, + { + model: Whatsapp, + as: "whatsapp", + attributes: ["qrcode", "type", "companyId"] + } + ] + }); + + if (!ticket) { + return res.status(404).json({ message: "Ticket not found" }); + } + + try { + if (medias) { + await Promise.all( + medias.map(async (media: Express.Multer.File) => { + await SendMediaMessageService( + media, + message, + ticket.id, + ticket.contact, + ticket.whatsapp, + companyId + ); + }) + ); + } else { + await SendTextMessageService( + message, + ticket.id, + ticket.contact, + ticket.whatsapp, + companyId + ); + } + + return res.status(200).json({ message: "Message sent" }); + } catch (error) { + console.log(error); + + return res.status(400).json({ message: error }); + } +}; + +export const store = async (req: Request, res: Response): Promise => { + const { contactId, status, userId, channel }: TicketData = req.body; + + const { companyId } = req.user; // Obtendo o companyId do usuário autenticado + + const ticket = await CreateHubTicketService({ + contactId, + status, + userId, + channel, + companyId // Passando o companyId na criação do ticket + }); + + const io = getIO(); + io.to(ticket.status).emit("ticket", { + action: "update", + ticket + }); + + return res.status(200).json(ticket); +}; \ No newline at end of file diff --git a/backend/src/controllers/PlanController.ts b/backend/src/controllers/PlanController.ts new file mode 100644 index 0000000..ecb718d --- /dev/null +++ b/backend/src/controllers/PlanController.ts @@ -0,0 +1,146 @@ +import * as Yup from "yup"; +import { Request, Response } from "express"; +// import { getIO } from "../libs/socket"; +import AppError from "../errors/AppError"; +import Plan from "../models/Plan"; + +import ListPlansService from "../services/PlanService/ListPlansService"; +import CreatePlanService from "../services/PlanService/CreatePlanService"; +import UpdatePlanService from "../services/PlanService/UpdatePlanService"; +import ShowPlanService from "../services/PlanService/ShowPlanService"; +import FindAllPlanServiceRegister from "../services/PlanService/FindAllPlanServiceRegister"; +import FindAllPlanService from "../services/PlanService/FindAllPlanService"; +import DeletePlanService from "../services/PlanService/DeletePlanService"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; +}; + +type StorePlanData = { + name: string; + id?: number | string; + users: number | 0; + connections: number | 0; + queues: number | 0; + value: number; + useCampaigns?: boolean; + useSchedules?: boolean; + useInternalChat?: boolean; + useExternalApi?: boolean; + useKanban?: boolean; + useOpenAi?: boolean; + useIntegrations?: boolean; + useInternal?: boolean; +}; + +type UpdatePlanData = { + name: string; + id?: number | string; + users?: number; + connections?: number; + queues?: number; + value?: number; + useCampaigns?: boolean; + useSchedules?: boolean; + useInternalChat?: boolean; + useExternalApi?: boolean; + useKanban?: boolean; + useOpenAi?: boolean; + useIntegrations?: boolean; + useInternal?: boolean; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + + const { plans, count, hasMore } = await ListPlansService({ + searchParam, + pageNumber + }); + + return res.json({ plans, count, hasMore }); +}; + +export const list = async (req: Request, res: Response): Promise => { + const plans: Plan[] = await FindAllPlanService(); + + return res.status(200).json(plans); +}; + +export const register = async (req: Request, res: Response): Promise => { + const plans: Plan[] = await FindAllPlanServiceRegister(); + + return res.status(200).json(plans); + }; + + +export const store = async (req: Request, res: Response): Promise => { + const newPlan: StorePlanData = req.body; + + const schema = Yup.object().shape({ + name: Yup.string().required() + }); + + try { + await schema.validate(newPlan); + } catch (err) { + throw new AppError(err.message); + } + + const plan = await CreatePlanService(newPlan); + + // const io = getIO(); + // io.emit("plan", { + // action: "create", + // plan + // }); + + return res.status(200).json(plan); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const plan = await ShowPlanService(id); + + return res.status(200).json(plan); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const planData: UpdatePlanData = req.body; + + const schema = Yup.object().shape({ + name: Yup.string() + }); + + try { + await schema.validate(planData); + } catch (err) { + throw new AppError(err.message); + } + + const plan = await UpdatePlanService(planData); + + // const io = getIO(); + // io.emit("plan", { + // action: "update", + // plan + // }); + + return res.status(200).json(plan); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + + const plan = await DeletePlanService(id); + + return res.status(200).json(plan); +}; diff --git a/backend/src/controllers/PromptController.ts b/backend/src/controllers/PromptController.ts new file mode 100644 index 0000000..d6969ba --- /dev/null +++ b/backend/src/controllers/PromptController.ts @@ -0,0 +1,114 @@ +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; +import CreatePromptService from "../services/PromptServices/CreatePromptService"; +import DeletePromptService from "../services/PromptServices/DeletePromptService"; +import ListPromptsService from "../services/PromptServices/ListPromptsService"; +import ShowPromptService from "../services/PromptServices/ShowPromptService"; +import UpdatePromptService from "../services/PromptServices/UpdatePromptService"; +import Whatsapp from "../models/Whatsapp"; +import { verify } from "jsonwebtoken"; +import authConfig from "../config/auth"; + +interface TokenPayload { + id: string; + username: string; + profile: string; + companyId: number; + iat: number; + exp: number; +} + +type IndexQuery = { + searchParam?: string; + pageNumber?: string | number; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { pageNumber, searchParam } = req.query as IndexQuery; + const authHeader = req.headers.authorization; + const [, token] = authHeader.split(" "); + const decoded = verify(token, authConfig.secret); + const { companyId } = decoded as TokenPayload; + const { prompts, count, hasMore } = await ListPromptsService({ searchParam, pageNumber, companyId }); + + return res.status(200).json({ prompts, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const authHeader = req.headers.authorization; + const [, token] = authHeader.split(" "); + const decoded = verify(token, authConfig.secret); + const { companyId } = decoded as TokenPayload; + const { name, apiKey, prompt, maxTokens, temperature, promptTokens, completionTokens, totalTokens, queueId, maxMessages,voice,voiceKey,voiceRegion } = req.body; + const promptTable = await CreatePromptService({ name, apiKey, prompt, maxTokens, temperature, promptTokens, completionTokens, totalTokens, queueId, maxMessages, companyId,voice,voiceKey,voiceRegion }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit("prompt", { + action: "update", + prompt: promptTable + }); + + return res.status(200).json(promptTable); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { promptId } = req.params; + const authHeader = req.headers.authorization; + const [, token] = authHeader.split(" "); + const decoded = verify(token, authConfig.secret); + const { companyId } = decoded as TokenPayload; + const prompt = await ShowPromptService({ promptId, companyId }); + + return res.status(200).json(prompt); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const { promptId } = req.params; + const promptData = req.body; + const authHeader = req.headers.authorization; + const [, token] = authHeader.split(" "); + const decoded = verify(token, authConfig.secret); + const { companyId } = decoded as TokenPayload; + + const prompt = await UpdatePromptService({ promptData, promptId: promptId, companyId }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit("prompt", { + action: "update", + prompt + }); + + return res.status(200).json(prompt); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { promptId } = req.params; + const authHeader = req.headers.authorization; + const [, token] = authHeader.split(" "); + const decoded = verify(token, authConfig.secret); + const { companyId } = decoded as TokenPayload; + try { + const { count } = await Whatsapp.findAndCountAll({ where: { promptId: +promptId, companyId } }); + + if (count > 0) return res.status(200).json({ message: "Não foi possível excluir! Verifique se este prompt está sendo usado nas conexões Whatsapp!" }); + + await DeletePromptService(promptId, companyId); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit("prompt", { + action: "delete", + intelligenceId: +promptId + }); + + return res.status(200).json({ message: "Prompt deleted" }); + } catch (err) { + return res.status(500).json({ message: "Não foi possível excluir! Verifique se este prompt está sendo usado!" }); + } +}; + diff --git a/backend/src/controllers/QueueController.ts b/backend/src/controllers/QueueController.ts new file mode 100644 index 0000000..753b528 --- /dev/null +++ b/backend/src/controllers/QueueController.ts @@ -0,0 +1,157 @@ +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; +import CreateQueueService from "../services/QueueService/CreateQueueService"; +import DeleteQueueService from "../services/QueueService/DeleteQueueService"; +import ListQueuesService from "../services/QueueService/ListQueuesService"; +import ShowQueueService from "../services/QueueService/ShowQueueService"; +import UpdateQueueService from "../services/QueueService/UpdateQueueService"; +import { isNil } from "lodash"; +import Queue from "../models/Queue"; +import { head } from "lodash"; +import fs from "fs"; +import path from "path"; +import AppError from "../errors/AppError"; + +type QueueFilter = { + companyId: number; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { companyId: userCompanyId } = req.user; + const { companyId: queryCompanyId } = req.query as unknown as QueueFilter; + let companyId = userCompanyId; + + if (!isNil(queryCompanyId)) { + companyId = +queryCompanyId; + } + + const queues = await ListQueuesService({ companyId }); + + return res.status(200).json(queues); +}; + +export const mediaUpload = async ( + req: Request, + res: Response +): Promise => { + const { queueId } = req.params; + const files = req.files as Express.Multer.File[]; + const file = head(files); + + try { + const queue = await Queue.findByPk(queueId); + + queue.update({ + mediaPath: file.filename, + mediaName: file.originalname + }); + + return res.send({ mensagem: "Arquivo Salvo" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; + +export const deleteMedia = async ( + req: Request, + res: Response +): Promise => { + const { queueId } = req.params; + + try { + const queue = await Queue.findByPk(queueId); + const filePath = path.resolve("public", queue.mediaPath); + const fileExists = fs.existsSync(filePath); + if (fileExists) { + fs.unlinkSync(filePath); + } + + queue.mediaPath = null; + queue.mediaName = null; + await queue.save(); + return res.send({ mensagem: "Arquivo excluído" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; + +export const store = async (req: Request, res: Response): Promise => { + const { name, color, greetingMessage, outOfHoursMessage, schedules, orderQueue, integrationId, promptId } = + req.body; + const { companyId } = req.user; + console.log("queue", integrationId, promptId) + const queue = await CreateQueueService({ + name, + color, + greetingMessage, + companyId, + outOfHoursMessage, + schedules, + orderQueue: orderQueue === "" ? null : orderQueue, + integrationId: integrationId === "" ? null : integrationId, + promptId: promptId === "" ? null : promptId + }); + + const io = getIO(); + io.emit(`company-${companyId}-queue`, { + action: "update", + queue + }); + + return res.status(200).json(queue); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { queueId } = req.params; + const { companyId } = req.user; + + const queue = await ShowQueueService(queueId, companyId); + + return res.status(200).json(queue); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const { queueId } = req.params; + const { companyId } = req.user; + const { name, color, greetingMessage, outOfHoursMessage, schedules, orderQueue, integrationId, promptId } = + req.body; + const queue = await UpdateQueueService(queueId, { + name, + color, + greetingMessage, + outOfHoursMessage, + schedules, + orderQueue: orderQueue === "" ? null : orderQueue, + integrationId: integrationId === "" ? null : integrationId, + promptId: promptId === "" ? null : promptId + }, companyId); + + const io = getIO(); + io.emit(`company-${companyId}-queue`, { + action: "update", + queue + }); + + return res.status(201).json(queue); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { queueId } = req.params; + const { companyId } = req.user; + + await DeleteQueueService(queueId, companyId); + + const io = getIO(); + io.emit(`company-${companyId}-queue`, { + action: "delete", + queueId: +queueId + }); + + return res.status(200).send(); +}; \ No newline at end of file diff --git a/backend/src/controllers/QueueIntegrationController.ts b/backend/src/controllers/QueueIntegrationController.ts new file mode 100644 index 0000000..7fbb095 --- /dev/null +++ b/backend/src/controllers/QueueIntegrationController.ts @@ -0,0 +1,99 @@ +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; +import CreateQueueIntegrationService from "../services/QueueIntegrationServices/CreateQueueIntegrationService"; +import DeleteQueueIntegrationService from "../services/QueueIntegrationServices/DeleteQueueIntegrationService"; +import ListQueueIntegrationService from "../services/QueueIntegrationServices/ListQueueIntegrationService"; +import ShowQueueIntegrationService from "../services/QueueIntegrationServices/ShowQueueIntegrationService"; +import UpdateQueueIntegrationService from "../services/QueueIntegrationServices/UpdateQueueIntegrationService"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + const { companyId } = req.user; + + const { queueIntegrations, count, hasMore } = await ListQueueIntegrationService({ + searchParam, + pageNumber, + companyId + }); + + return res.status(200).json({ queueIntegrations, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { type, name, projectName, jsonContent, language, urlN8N, + typebotExpires, + typebotKeywordFinish, + typebotSlug, + typebotUnknownMessage, + typebotKeywordRestart, + typebotRestartMessage } = req.body; + const { companyId } = req.user; + const queueIntegration = await CreateQueueIntegrationService({ + type, name, projectName, jsonContent, language, urlN8N, companyId, + typebotExpires, + typebotKeywordFinish, + typebotSlug, + typebotUnknownMessage, + typebotKeywordRestart, + typebotRestartMessage + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-queueIntegration`, { + action: "create", + queueIntegration + }); + + return res.status(200).json(queueIntegration); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { integrationId } = req.params; + const { companyId } = req.user; + + const queueIntegration = await ShowQueueIntegrationService(integrationId, companyId); + + return res.status(200).json(queueIntegration); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const { integrationId } = req.params; + const integrationData = req.body; + const { companyId } = req.user; + + const queueIntegration = await UpdateQueueIntegrationService({ integrationData, integrationId, companyId }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-queueIntegration`, { + action: "update", + queueIntegration + }); + + return res.status(201).json(queueIntegration); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { integrationId } = req.params; + const { companyId } = req.user; + + await DeleteQueueIntegrationService(integrationId); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-queueIntegration`, { + action: "delete", + integrationId: +integrationId + }); + + return res.status(200).send(); +}; \ No newline at end of file diff --git a/backend/src/controllers/QueueOptionController.ts b/backend/src/controllers/QueueOptionController.ts new file mode 100644 index 0000000..974f0b6 --- /dev/null +++ b/backend/src/controllers/QueueOptionController.ts @@ -0,0 +1,110 @@ +import { Request, Response } from "express"; + +import CreateService from "../services/QueueOptionService/CreateService"; +import ListService from "../services/QueueOptionService/ListService"; +import UpdateService from "../services/QueueOptionService/UpdateService"; +import ShowService from "../services/QueueOptionService/ShowService"; +import DeleteService from "../services/QueueOptionService/DeleteService"; +import { head } from "lodash"; +import fs from "fs"; +import path from "path"; +import AppError from "../errors/AppError"; +import QueueOption from "../models/QueueOption"; + +type FilterList = { + queueId: string | number; + queueOptionId: string | number; + parentId: string | number | boolean; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { queueId, queueOptionId, parentId } = req.query as FilterList; + + const queueOptions = await ListService({ queueId, queueOptionId, parentId }); + + return res.json(queueOptions); +}; + +export const store = async (req: Request, res: Response): Promise => { + const queueOptionData = req.body; + + const queueOption = await CreateService(queueOptionData); + + return res.status(200).json(queueOption); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { queueOptionId } = req.params; + + const queueOption = await ShowService(queueOptionId); + + return res.status(200).json(queueOption); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const { queueOptionId } = req.params + const queueOptionData = req.body; + + const queueOption = await UpdateService(queueOptionId, queueOptionData); + + return res.status(200).json(queueOption); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { queueOptionId } = req.params + + await DeleteService(queueOptionId); + + return res.status(200).json({ message: "Option Delected" }); +}; + +export const mediaUpload = async ( + req: Request, + res: Response +): Promise => { + const { queueOptionId } = req.params; + const files = req.files as Express.Multer.File[]; + const file = head(files); + + try { + const queue = await QueueOption.findByPk(queueOptionId); + + queue.update({ + mediaPath: file.filename, + mediaName: file.originalname + }); + + return res.send({ mensagem: "Arquivo Salvo" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; + +export const deleteMedia = async ( + req: Request, + res: Response +): Promise => { + const { queueOptionId } = req.params; + + try { + const queue = await QueueOption.findByPk(queueOptionId); + const filePath = path.resolve("public", queue.mediaPath); + const fileExists = fs.existsSync(filePath); + if (fileExists) { + fs.unlinkSync(filePath); + } + + queue.mediaPath = null; + queue.mediaName = null; + await queue.save(); + return res.send({ mensagem: "Arquivo excluído" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; \ No newline at end of file diff --git a/backend/src/controllers/QuickMessageController.ts b/backend/src/controllers/QuickMessageController.ts new file mode 100644 index 0000000..c651c53 --- /dev/null +++ b/backend/src/controllers/QuickMessageController.ts @@ -0,0 +1,223 @@ +import * as Yup from "yup"; +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; + +import ListService from "../services/QuickMessageService/ListService"; +import CreateService from "../services/QuickMessageService/CreateService"; +import ShowService from "../services/QuickMessageService/ShowService"; +import UpdateService from "../services/QuickMessageService/UpdateService"; +import DeleteService from "../services/QuickMessageService/DeleteService"; +import FindService from "../services/QuickMessageService/FindService"; + +import QuickMessage from "../models/QuickMessage"; + +import { head } from "lodash"; +import fs from "fs"; +import path from "path"; + +import AppError from "../errors/AppError"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; + userId: string | number; +}; + +type StoreData = { + shortcode: string; + message: string; + userId: number | number; + geral: boolean; +}; + +type FindParams = { + companyId: string; + userId: string; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + const { companyId, id: userId } = req.user; + + const { records, count, hasMore } = await ListService({ + searchParam, + pageNumber, + companyId, + userId + }); + + return res.json({ records, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + const data = req.body as StoreData; + + const schema = Yup.object().shape({ + shortcode: Yup.string().required(), + message: Yup.string().required() + }); + + try { + await schema.validate(data); + } catch (err: any) { + throw new AppError(err.message); + } + + const record = await CreateService({ + ...data, + companyId, + userId: req.user.id + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-quickmessage`, { + action: "create", + record + }); + + return res.status(200).json(record); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const record = await ShowService(id); + + return res.status(200).json(record); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const data = req.body as StoreData; + const { companyId } = req.user; + + const schema = Yup.object().shape({ + shortcode: Yup.string().required(), + message: Yup.string().required() + }); + + try { + await schema.validate(data); + } catch (err: any) { + throw new AppError(err.message); + } + + const { id } = req.params; + + const record = await UpdateService({ + ...data, + userId: req.user.id, + id, + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-quickmessage`, { + action: "update", + record + }); + + return res.status(200).json(record); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const { companyId } = req.user; + + await DeleteService(id); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-quickmessage`, { + action: "delete", + id + }); + + return res.status(200).json({ message: "Contact deleted" }); +}; + +export const findList = async ( + req: Request, + res: Response +): Promise => { + const params = req.query as FindParams; + const records: QuickMessage[] = await FindService(params); + + return res.status(200).json(records); +}; + +export const mediaUpload = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const files = req.files as Express.Multer.File[]; + const file = head(files); + + try { + const quickmessage = await QuickMessage.findByPk(id); + + quickmessage.update ({ + mediaPath: file.filename, + mediaName: file.originalname + }); + + return res.send({ mensagem: "Arquivo Anexado" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; + +export const deleteMedia = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const { companyId } = req.user + + try { + // Encontre a mensagem rápida + const quickmessage = await QuickMessage.findByPk(id); + + // Verifique se a mensagem foi encontrada + if (!quickmessage) { + throw new AppError("Arquivo não encontrado", 404); + } + + // Aplique a mesma lógica de renomeação para gerar o nome correto do arquivo + let filename = quickmessage.mediaName; + + // Se o filename já tiver sido alterado (adicionando timestamp), remova esse prefixo + const timestampRegex = /^\d+_/; + if (timestampRegex.test(filename)) { + // Remover o timestamp do começo do nome do arquivo + filename = filename.replace(timestampRegex, ''); + } + + const filePath = path.resolve( + "public", + `company${companyId}`, + "quick", + filename + ); + + const fileExists = fs.existsSync(filePath); + if (fileExists) { + fs.unlinkSync(filePath); // Exclui o arquivo + } + + // Atualiza os dados da mensagem no banco + await quickmessage.update({ + mediaPath: null, + mediaName: null + }); + + return res.send({ mensagem: "Arquivo Excluído" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; \ No newline at end of file diff --git a/backend/src/controllers/ReportsController.ts b/backend/src/controllers/ReportsController.ts new file mode 100644 index 0000000..2d659fe --- /dev/null +++ b/backend/src/controllers/ReportsController.ts @@ -0,0 +1,105 @@ +import { Request, Response } from 'express'; +import { QueryTypes } from 'sequelize'; + +import sequelize from '../database'; + +type RequestQueryProps = { + companyId: string; + initialDate: string; + finalDate: string; +}; + +export const appointmentsAtendent = async ( + req: Request, + res: Response, +): Promise => { + const { companyId, initialDate, finalDate } = req.query as RequestQueryProps; + + const resultAppointmentsByAttendents = await sequelize.query( + ` + SELECT + u."name" as user_name + ,COUNT(t.*) as total_tickets + FROM "Users" u + LEFT JOIN "TicketTraking" tt ON tt."userId" = u.id + LEFT JOIN "Tickets" t ON t.id = tt."ticketId" AND t."createdAt" BETWEEN '${initialDate}' AND '${finalDate}' + where u."companyId" = ${companyId} + GROUP BY u."name" + ORDER BY total_tickets ASC + `, + { type: QueryTypes.SELECT }, + ); + + const resultTicketsByQueues = await sequelize.query( + ` + SELECT + q."name" + ,COUNT(DISTINCT t.id) as total_tickets + FROM "Queues" q + LEFT JOIN "Messages" m ON m."queueId" = q.id + LEFt JOIN "Tickets" t ON t.id = m."ticketId" AND t."createdAt" BETWEEN '${initialDate}' AND '${finalDate}' + WHERE q."companyId" = ${companyId} + GROUP BY q."name" + ORDER BY total_tickets ASC + `, + { type: QueryTypes.SELECT }, + ); + + return res.json({ + appointmentsByAttendents: resultAppointmentsByAttendents, + ticketsByQueues: resultTicketsByQueues, + }); +}; + +export const rushHour = async ( + req: Request, + res: Response, +): Promise => { + const { companyId, initialDate, finalDate } = req.query as RequestQueryProps; + + const resultAppointmentsByHours = await sequelize.query( + ` + SELECT + extract (hour from m."createdAt") AS message_hour, + COUNT(m.id) AS message_count + FROM "Messages" m + LEFT JOIN "Tickets" t ON t.id = m."ticketId" + WHERE t."companyId" = ${companyId} + AND m."createdAt" BETWEEN '${initialDate}' AND '${finalDate}' + GROUP BY + extract (hour from m."createdAt") + ORDER BY + extract (hour from m."createdAt") + `, + { type: QueryTypes.SELECT }, + ); + + return res.json(resultAppointmentsByHours); +}; + +export const departamentRatings = async ( + req: Request, + res: Response, +): Promise => { + const { companyId, initialDate, finalDate } = req.query as RequestQueryProps; + + const resultDepartamentRating = await sequelize.query( + ` + SELECT + m."ticketId" + ,q."name" + ,round(avg(ur.rate), 2) AS total_rate + FROM "Messages" m + LEFT JOIN "Tickets" t ON t.id = m."ticketId" + LEFT JOIN "UserRatings" ur ON ur."ticketId" = t.id + LEFT JOIN "Queues" q ON q.id = m."queueId" + WHERE m."queueId" IS NOT NULL + AND m."companyId" = ${companyId} + AND ur."createdAt" BETWEEN '${initialDate}' AND '${finalDate}' + GROUP BY m."ticketId", q."name" + `, + { type: QueryTypes.SELECT }, + ); + + return res.json(resultDepartamentRating); +}; diff --git a/backend/src/controllers/ScheduleController.ts b/backend/src/controllers/ScheduleController.ts new file mode 100644 index 0000000..51df02f --- /dev/null +++ b/backend/src/controllers/ScheduleController.ts @@ -0,0 +1,154 @@ +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; + +import AppError from "../errors/AppError"; + +import CreateService from "../services/ScheduleServices/CreateService"; +import ListService from "../services/ScheduleServices/ListService"; +import UpdateService from "../services/ScheduleServices/UpdateService"; +import ShowService from "../services/ScheduleServices/ShowService"; +import DeleteService from "../services/ScheduleServices/DeleteService"; +import Schedule from "../models/Schedule"; +import path from "path"; +import fs from "fs"; +import { head } from "lodash"; + +type IndexQuery = { + searchParam?: string; + contactId?: number | string; + userId?: number | string; + pageNumber?: string | number; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { contactId, userId, pageNumber, searchParam } = req.query as IndexQuery; + const { companyId } = req.user; + + const { schedules, count, hasMore } = await ListService({ + searchParam, + contactId, + userId, + pageNumber, + companyId + }); + + return res.json({ schedules, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { + body, + sendAt, + contactId, + userId + } = req.body; + const { companyId } = req.user; + + const schedule = await CreateService({ + body, + sendAt, + contactId, + companyId, + userId + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit("schedule", { + action: "create", + schedule + }); + + return res.status(200).json(schedule); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { scheduleId } = req.params; + const { companyId } = req.user; + + const schedule = await ShowService(scheduleId, companyId); + + return res.status(200).json(schedule); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + if (req.user.profile !== "admin") { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + const { scheduleId } = req.params; + const scheduleData = req.body; + const { companyId } = req.user; + + const schedule = await UpdateService({ scheduleData, id: scheduleId, companyId }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit("schedule", { + action: "update", + schedule + }); + + return res.status(200).json(schedule); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { scheduleId } = req.params; + const { companyId } = req.user; + + await DeleteService(scheduleId, companyId); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit("schedule", { + action: "delete", + scheduleId + }); + + return res.status(200).json({ message: "Schedule deleted" }); +}; + +export const mediaUpload = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + const files = req.files as Express.Multer.File[]; + const file = head(files); + + try { + const schedule = await Schedule.findByPk(id); + schedule.mediaPath = file.filename; + schedule.mediaName = file.originalname; + + await schedule.save(); + return res.send({ mensagem: "Arquivo Anexado" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; + +export const deleteMedia = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + + try { + const schedule = await Schedule.findByPk(id); + const filePath = path.resolve("public", schedule.mediaPath); + const fileExists = fs.existsSync(filePath); + if (fileExists) { + fs.unlinkSync(filePath); + } + schedule.mediaPath = null; + schedule.mediaName = null; + await schedule.save(); + return res.send({ mensagem: "Arquivo Excluído" }); + } catch (err: any) { + throw new AppError(err.message); + } +}; \ No newline at end of file diff --git a/backend/src/controllers/SessionController.ts b/backend/src/controllers/SessionController.ts new file mode 100644 index 0000000..9dabe76 --- /dev/null +++ b/backend/src/controllers/SessionController.ts @@ -0,0 +1,80 @@ +import { Request, Response } from "express"; +import AppError from "../errors/AppError"; +import { getIO } from "../libs/socket"; + +import AuthUserService from "../services/UserServices/AuthUserService"; +import { SendRefreshToken } from "../helpers/SendRefreshToken"; +import { RefreshTokenService } from "../services/AuthServices/RefreshTokenService"; +import FindUserFromToken from "../services/AuthServices/FindUserFromToken"; +import User from "../models/User"; + +export const store = async (req: Request, res: Response): Promise => { + const { email, password } = req.body; + + const { token, serializedUser, refreshToken } = await AuthUserService({ + email, + password + }); + + SendRefreshToken(res, refreshToken); + + const io = getIO(); + io.to(`user-${serializedUser.id}`).emit(`company-${serializedUser.companyId}-auth`, { + action: "update", + user: { + id: serializedUser.id, + email: serializedUser.email, + companyId: serializedUser.companyId + } + }); + + return res.status(200).json({ + token, + user: serializedUser + }); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const token: string = req.cookies.jrt; + + if (!token) { + throw new AppError("ERR_SESSION_EXPIRED", 401); + } + + const { user, newToken, refreshToken } = await RefreshTokenService( + res, + token + ); + + SendRefreshToken(res, refreshToken); + + return res.json({ token: newToken, user }); +}; + +export const me = async (req: Request, res: Response): Promise => { + const token: string = req.cookies.jrt; + const user = await FindUserFromToken(token); + const { id, profile, super: superAdmin } = user; + + if (!token) { + throw new AppError("ERR_SESSION_EXPIRED", 401); + } + + return res.json({ id, profile, super: superAdmin }); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.user; + const user = await User.findByPk(id); + await user.update({ online: false }); + + res.clearCookie("jrt"); + + return res.send(); +}; diff --git a/backend/src/controllers/SettingController.ts b/backend/src/controllers/SettingController.ts new file mode 100644 index 0000000..2dd81f3 --- /dev/null +++ b/backend/src/controllers/SettingController.ts @@ -0,0 +1,158 @@ +import { Request, Response } from "express"; +import authConfig from "../config/auth"; +import * as Yup from "yup"; + +import { getIO } from "../libs/socket"; +import AppError from "../errors/AppError"; + +import { head } from "lodash"; +import fs from "fs"; +import path from "path"; +import User from "../models/User"; +import Company from "../models/Company"; + +import UpdateSettingService from "../services/SettingServices/UpdateSettingService"; +import ListSettingsService from "../services/SettingServices/ListSettingsService"; +import ShowSettingsService from "../services/SettingServices/ShowSettingsService"; + +export const index = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + + //if (req.user.profile !== "admin") { + //throw new AppError("ERR_NO_PERMISSION", 403); + //} + + const settings = await ListSettingsService({ companyId }); + + return res.status(200).json(settings); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + if (req.user.profile !== "admin") { + throw new AppError("ERR_NO_PERMISSION", 403); + } + const { settingKey: key } = req.params; + const { value } = req.body; + const { companyId } = req.user; + + const setting = await UpdateSettingService({ + key, + value, + companyId + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-settings`, { + action: "update", + setting + }); + + return res.status(200).json(setting); +}; + + +export const show = async ( + req: Request, + res: Response +): Promise => { + + //const { companyId } = req.user; + const companyId = 1; + const { settingKey } = req.params; + + + const retornoData = await ShowSettingsService({ settingKey, companyId }); + + return res.status(200).json(retornoData); +}; + + +export const mediaUpload = async ( + req: Request, + res: Response +): Promise => { + const { body } = req.body; + const { companyId } = req.user; + + const userId = req.user.id; + const requestUser = await User.findByPk(userId); + + if (requestUser.super === false) { + throw new AppError("você nao tem permissão para esta ação!"); + } + + if (req.user.profile !== "admin") { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + if (companyId !== 1) { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + const files = req.files as Express.Multer.File[]; + const file = head(files); + console.log(file); + return res.send({ mensagem: "Arquivo Anexado" }); +}; + + +export const certUpload = async ( + req: Request, + res: Response +): Promise => { + const { body } = req.body; + const { companyId } = req.user; + + const userId = req.user.id; + const requestUser = await User.findByPk(userId); + + if (requestUser.super === false) { + throw new AppError("você nao tem permissão para esta ação!"); + } + + if (req.user.profile !== "admin") { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + if (companyId !== 1) { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + const files = req.files as Express.Multer.File[]; + const file = head(files); + console.log(file); + return res.send({ mensagem: "Arquivo Anexado" }); +}; + + + +export const docUpload = async ( + req: Request, + res: Response +): Promise => { + const { body } = req.body; + const { companyId } = req.user; + + const userId = req.user.id; + const requestUser = await User.findByPk(userId); + + if (requestUser.super === false) { + throw new AppError("você nao tem permissão para esta ação!"); + } + + if (req.user.profile !== "admin") { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + if (companyId !== 1) { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + const files = req.files as Express.Multer.File[]; + const file = head(files); + console.log(file); + return res.send({ mensagem: "Arquivo Anexado" }); +}; diff --git a/backend/src/controllers/SubscriptionController.ts b/backend/src/controllers/SubscriptionController.ts new file mode 100644 index 0000000..e61be82 --- /dev/null +++ b/backend/src/controllers/SubscriptionController.ts @@ -0,0 +1,199 @@ +import { Request, Response } from "express"; +import express from "express"; +import * as Yup from "yup"; +import Gerencianet from "gn-api-sdk-typescript"; +import AppError from "../errors/AppError"; + +import options from "../config/Gn"; +import Company from "../models/Company"; +import Invoices from "../models/Invoices"; +import Subscriptions from "../models/Subscriptions"; +import { getIO } from "../libs/socket"; +import UpdateUserService from "../services/UserServices/UpdateUserService"; + +const app = express(); + + +export const index = async (req: Request, res: Response): Promise => { + const gerencianet = Gerencianet(options); + return res.json(gerencianet.getSubscriptions()); +}; + +export const createSubscription = async ( + req: Request, + res: Response + ): Promise => { + const gerencianet = Gerencianet(options); + const { companyId } = req.user; + + const schema = Yup.object().shape({ + price: Yup.string().required(), + users: Yup.string().required(), + connections: Yup.string().required() + }); + + if (!(await schema.isValid(req.body))) { + throw new AppError("Validation fails", 400); + } + + const { + firstName, + price, + users, + connections, + address2, + city, + state, + zipcode, + country, + plan, + invoiceId + } = req.body; + + + const body = { + calendario: { + expiracao: 3600 + }, + valor: { + original: price.toLocaleString("pt-br", { minimumFractionDigits: 2 }).replace(",", ".") + }, + chave: process.env.GERENCIANET_PIX_KEY, + solicitacaoPagador: `#Fatura:${invoiceId}` + }; + try { + const pix = await gerencianet.pixCreateImmediateCharge(null, body); + + const qrcode = await gerencianet.pixGenerateQRCode({ + id: pix.loc.id + }); + + const updateCompany = await Company.findOne(); + + if (!updateCompany) { + throw new AppError("Company not found", 404); + } + + +/* await Subscriptions.create({ + companyId, + isActive: false, + userPriceCents: users, + whatsPriceCents: connections, + lastInvoiceUrl: pix.location, + lastPlanChange: new Date(), + providerSubscriptionId: pix.loc.id, + expiresAt: new Date() + }); */ + +/* const { id } = req.user; + const userData = {}; + const userId = id; + const requestUserId = parseInt(id); + const user = await UpdateUserService({ userData, userId, companyId, requestUserId }); */ + + /* const io = getIO(); + io.emit("user", { + action: "update", + user + }); */ + + + return res.json({ + ...pix, + qrcode, + + }); + } catch (error) { + throw new AppError("Validation fails", 400); + } +}; + +export const createWebhook = async ( + req: Request, + res: Response +): Promise => { + const schema = Yup.object().shape({ + chave: Yup.string().required(), + url: Yup.string().required() + }); + + if (!(await schema.isValid(req.body))) { + throw new AppError("Validation fails", 400); + } + + const { chave, url } = req.body; + + const body = { + webhookUrl: url + }; + + const params = { + chave + }; + + try { + const gerencianet = Gerencianet(options); + const create = await gerencianet.pixConfigWebhook(params, body); + return res.json(create); + } catch (error) { + console.log(error); + } +}; + +export const webhook = async ( + req: Request, + res: Response + ): Promise => { + const { type } = req.params; + const { evento } = req.body; + if (evento === "teste_webhook") { + return res.json({ ok: true }); + } + if (req.body.pix) { + const gerencianet = Gerencianet(options); + req.body.pix.forEach(async (pix: any) => { + const detahe = await gerencianet.pixDetailCharge({ + txid: pix.txid + }); + + if (detahe.status === "CONCLUIDA") { + const { solicitacaoPagador } = detahe; + const invoiceID = solicitacaoPagador.replace("#Fatura:", ""); + const invoices = await Invoices.findByPk(invoiceID); + const companyId =invoices.companyId; + const company = await Company.findByPk(companyId); + + const expiresAt = new Date(company.dueDate); + expiresAt.setDate(expiresAt.getDate() + 30); + const date = expiresAt.toISOString().split("T")[0]; + + if (company) { + await company.update({ + dueDate: date + }); + const invoi = await invoices.update({ + id: invoiceID, + status: 'paid' + }); + await company.reload(); + const io = getIO(); + const companyUpdate = await Company.findOne({ + where: { + id: companyId + } + }); + + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-payment`, { + action: detahe.status, + company: companyUpdate + }); + } + + } + }); + + } + + return res.json({ ok: true }); +}; diff --git a/backend/src/controllers/TagController.ts b/backend/src/controllers/TagController.ts new file mode 100644 index 0000000..4de55cd --- /dev/null +++ b/backend/src/controllers/TagController.ts @@ -0,0 +1,128 @@ +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; + +import AppError from "../errors/AppError"; + +import CreateService from "../services/TagServices/CreateService"; +import ListService from "../services/TagServices/ListService"; +import UpdateService from "../services/TagServices/UpdateService"; +import ShowService from "../services/TagServices/ShowService"; +import DeleteService from "../services/TagServices/DeleteService"; +import SimpleListService from "../services/TagServices/SimpleListService"; +import SyncTagService from "../services/TagServices/SyncTagsService"; +import KanbanListService from "../services/TagServices/KanbanListService"; + +type IndexQuery = { + searchParam?: string; + pageNumber?: string | number; + kanban?: number; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { pageNumber, searchParam } = req.query as IndexQuery; + const { companyId } = req.user; + + const { tags, count, hasMore } = await ListService({ + searchParam, + pageNumber, + companyId + }); + + return res.json({ tags, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { name, color, kanban } = req.body; + const { companyId } = req.user; + + const tag = await CreateService({ + name, + color, + companyId, + kanban + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit("tag", { + action: "create", + tag + }); + + return res.status(200).json(tag); +}; + +export const kanban = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + + const tags = await KanbanListService({ companyId }); + + return res.json({lista:tags}); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { tagId } = req.params; + + const tag = await ShowService(tagId); + + return res.status(200).json(tag); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + if (req.user.profile !== "admin") { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + const { tagId } = req.params; + const tagData = req.body; + + const tag = await UpdateService({ tagData, id: tagId }); + + const io = getIO(); + io.to(`company-${req.user.companyId}-mainchannel`).emit("tag", { + action: "update", + tag + }); + + return res.status(200).json(tag); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { tagId } = req.params; + + await DeleteService(tagId); + + const io = getIO(); + io.to(`company-${req.user.companyId}-mainchannel`).emit("tag", { + action: "delete", + tagId + }); + + return res.status(200).json({ message: "Tag deleted" }); +}; + +export const list = async (req: Request, res: Response): Promise => { + const { searchParam } = req.query as IndexQuery; + const { companyId } = req.user; + + const tags = await SimpleListService({ searchParam, companyId }); + + return res.json(tags); +}; + +export const syncTags = async ( + req: Request, + res: Response +): Promise => { + const data = req.body; + const { companyId } = req.user; + + const tags = await SyncTagService({ ...data, companyId }); + + return res.json(tags); +}; diff --git a/backend/src/controllers/TicketController.ts b/backend/src/controllers/TicketController.ts new file mode 100644 index 0000000..3c0b15c --- /dev/null +++ b/backend/src/controllers/TicketController.ts @@ -0,0 +1,378 @@ +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; +import Ticket from "../models/Ticket"; + +import CreateTicketService from "../services/TicketServices/CreateTicketService"; +import DeleteTicketService from "../services/TicketServices/DeleteTicketService"; +import ListTicketsService from "../services/TicketServices/ListTicketsService"; +import ShowTicketUUIDService from "../services/TicketServices/ShowTicketFromUUIDService"; +import ShowTicketService from "../services/TicketServices/ShowTicketService"; +import ListTicketsServiceReport from "../services/TicketServices/ListTicketsServiceReport"; +import UpdateTicketService from "../services/TicketServices/UpdateTicketService"; +import ListTicketsServiceKanban from "../services/TicketServices/ListTicketsServiceKanban"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; + status: string; + date: string; + updatedAt?: string; + showAll: string; + withUnreadMessages: string; + queueIds: string; + tags: string; + users: string; +}; + +interface TicketData { + contactId: number; + status: string; + queueId: number; + userId: number; + whatsappId: string; + useIntegration: boolean; + promptId: number; + integrationId: number; +} + +type IndexQueryReport = { + searchParam: string; + contactId: string; + whatsappId: string; + dateFrom: string; + dateTo: string; + status: string; + //lastMessage: string; + queueIds: string; + tags: string; + users: string; + page: string; + pageSize: string; +}; + +export const index = async (req: Request, res: Response): Promise => { + + console.log("FUNÇÃO INDEX EXECUTADA"); + const { + pageNumber, + status, + date, + updatedAt, + searchParam, + showAll, + queueIds: queueIdsStringified, + tags: tagIdsStringified, + users: userIdsStringified, + withUnreadMessages + } = req.query as IndexQuery; + + const userId = req.user.id; + const { companyId } = req.user; + + let queueIds: number[] = []; + let tagsIds: number[] = []; + let usersIds: number[] = []; + + if (queueIdsStringified) { + queueIds = JSON.parse(queueIdsStringified); + } + + if (tagIdsStringified) { + tagsIds = JSON.parse(tagIdsStringified); + } + + if (userIdsStringified) { + usersIds = JSON.parse(userIdsStringified); + } + + const { tickets, count, hasMore } = await ListTicketsService({ + searchParam, + tags: tagsIds, + users: usersIds, + pageNumber, + status, + date, + updatedAt, + showAll, + userId, + queueIds, + withUnreadMessages, + companyId, + + + }); + return res.status(200).json({ tickets, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + + console.log("FUNÇÃO STORE EXECUTADA"); + + const { contactId, status, userId, queueId, whatsappId }: TicketData = req.body; + const { companyId } = req.user; + + const ticket = await CreateTicketService({ + contactId, + status, + userId, + companyId, + queueId, + whatsappId + }); + + const io = getIO(); + io.to(ticket.status).emit(`company-${companyId}-ticket`, { + action: "update", + ticket + }); + return res.status(200).json(ticket); +}; + +export const kanban = async (req: Request, res: Response): Promise => { + + console.log("FUNÇÃO KANBAN EXECUTADA"); + + const { + pageNumber, + status, + date, + updatedAt, + searchParam, + showAll, + queueIds: queueIdsStringified, + tags: tagIdsStringified, + users: userIdsStringified, + withUnreadMessages + } = req.query as IndexQuery; + + + const userId = req.user.id; + const { companyId } = req.user; + + let queueIds: number[] = []; + let tagsIds: number[] = []; + let usersIds: number[] = []; + + if (queueIdsStringified) { + queueIds = JSON.parse(queueIdsStringified); + } + + if (tagIdsStringified) { + tagsIds = JSON.parse(tagIdsStringified); + } + + if (userIdsStringified) { + usersIds = JSON.parse(userIdsStringified); + } + + const { tickets, count, hasMore } = await ListTicketsServiceKanban({ + searchParam, + tags: tagsIds, + users: usersIds, + pageNumber, + status, + date, + updatedAt, + showAll, + userId, + queueIds, + withUnreadMessages, + companyId + + }); + + return res.status(200).json({ tickets, count, hasMore }); +}; + +export const show = async (req: Request, res: Response): Promise => { + + console.log("FUNÇÃO SHOW EXECUTADA"); + + const { ticketId } = req.params; + const { companyId } = req.user; + + console.log("VALOR DE ticketId NA FUNÇÃO SHOW:", ticketId); // Novo log para ver o valor + + if (!ticketId || ticketId === "undefined" || isNaN(+ticketId)) { + console.log("ERRO: ticketId inválido detectado na função SHOW:", ticketId); + return res.status(400).json({ error: "Ticket ID inválido" }); + } + + const contact = await ShowTicketService(ticketId, companyId); + return res.status(200).json(contact); +}; + +export const showFromUUID = async ( + req: Request, + res: Response +): Promise => { + const { uuid } = req.params; + + const ticket: Ticket = await ShowTicketUUIDService(uuid); + + return res.status(200).json(ticket); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + + console.log("FUNÇÃO UPDATE EXECUTADA"); + + const { ticketId } = req.params; + const ticketData: TicketData = req.body; + const { companyId } = req.user; + + console.log("VALOR DE ticketId NA FUNÇÃO UPDATE:", ticketId); // Novo log + console.log("DADOS ENVIADOS NA FUNÇÃO UPDATE:", ticketData); // Novo log + + const { ticket } = await UpdateTicketService({ + ticketData, + ticketId, + companyId + }); + + console.log("TICKET RETORNADO POR UPDATE:", ticket); // Novo log + + return res.status(200).json(ticket); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + + console.log("FUNÇÃO REMOVE EXECUTADA"); + + const { ticketId } = req.params; + const { companyId } = req.user; + + await ShowTicketService(ticketId, companyId); + + const ticket = await DeleteTicketService(ticketId); + + const io = getIO(); + io.to(ticketId) + .to(`company-${companyId}-${ticket.status}`) + .to(`company-${companyId}-notification`) + .to(`queue-${ticket.queueId}-${ticket.status}`) + .to(`queue-${ticket.queueId}-notification`) + .emit(`company-${companyId}-ticket`, { + action: "delete", + ticketId: +ticketId + }); + + return res.status(200).json({ message: "ticket deleted" }); +}; + + +export const report = async (req: Request, res: Response): Promise => { + + console.log("FUNÇÃO REPORT EXECUTADA"); + + const { + searchParam, + contactId, + whatsappId: whatsappIdsStringified, + dateFrom, + dateTo, + status: statusStringified, + //lastMessage, + queueIds: queueIdsStringified, + tags: tagIdsStringified, + users: userIdsStringified, + page: pageNumber, + pageSize + } = req.query as IndexQueryReport; + + const userId = req.user.id; + const { companyId } = req.user; + + let queueIds: number[] = []; + let whatsappIds: string[] = []; + let tagsIds: number[] = []; + let usersIds: number[] = []; + let statusIds: string[] = []; + + + if (statusStringified) { + statusIds = JSON.parse(statusStringified); + } + + if (whatsappIdsStringified) { + whatsappIds = JSON.parse(whatsappIdsStringified); + } + + if (queueIdsStringified) { + queueIds = JSON.parse(queueIdsStringified); + } + + if (tagIdsStringified) { + tagsIds = JSON.parse(tagIdsStringified); + } + + if (userIdsStringified) { + usersIds = JSON.parse(userIdsStringified); + } + + const { tickets, totalTickets } = await ListTicketsServiceReport( + companyId, + { + searchParam, + queueIds, + tags: tagsIds, + users: usersIds, + status: statusIds, + dateFrom, + dateTo, + userId, + contactId, + whatsappId: whatsappIds + }, + +pageNumber, + +pageSize + ); + + return res.status(200).json({ tickets, totalTickets }); +}; + +export const closeAll = async (req: Request, res: Response): Promise => { + + console.log("FUNÇÃO CLOSEALL EXECUTADA"); + + const { companyId } = req.user; + const { status }: TicketData = req.body; + const io = getIO(); + + const { rows: tickets } = await Ticket.findAndCountAll({ + where: { companyId: companyId, status: status }, + order: [["updatedAt", "DESC"]] + }); + + tickets.forEach(async ticket => { + + await ticket.update({ + status: "closed", + useIntegration: false, + promptId: null, + integrationId: null, + unreadMessages: 0 + }) + + const io = getIO(); + io.to(`${ticket.id}`) + .to(`company-${companyId}-${ticket.status}`) + .to(`company-${companyId}-notification`) + .to(`queue-${ticket.queueId}-${ticket.status}`) + .to(`queue-${ticket.queueId}-notification`) + .emit(`company-${companyId}-ticket`, { + action: "delete", + ticketId: ticket.id + }); + + }); + + return res.status(200).json(); +}; + diff --git a/backend/src/controllers/TicketNoteController.ts b/backend/src/controllers/TicketNoteController.ts new file mode 100644 index 0000000..42a4379 --- /dev/null +++ b/backend/src/controllers/TicketNoteController.ts @@ -0,0 +1,138 @@ +import * as Yup from "yup"; +import { Request, Response } from "express"; +import AppError from "../errors/AppError"; +import TicketNote from "../models/TicketNote"; + +import ListTicketNotesService from "../services/TicketNoteService/ListTicketNotesService"; +import CreateTicketNoteService from "../services/TicketNoteService/CreateTicketNoteService"; +import UpdateTicketNoteService from "../services/TicketNoteService/UpdateTicketNoteService"; +import ShowTicketNoteService from "../services/TicketNoteService/ShowTicketNoteService"; +import FindAllTicketNotesService from "../services/TicketNoteService/FindAllTicketNotesService"; +import DeleteTicketNoteService from "../services/TicketNoteService/DeleteTicketNoteService"; +import FindNotesByContactIdAndTicketId from "../services/TicketNoteService/FindNotesByContactIdAndTicketId"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; +}; + +type StoreTicketNoteData = { + note: string; + userId: number; + contactId: number | 0; + ticketId: number | 0; + id?: number | string; +}; + +type UpdateTicketNoteData = { + note: string; + id?: number | string; + userId?: number | 0; + contactId?: number | 0; + ticketId?: number | 0; +}; + +type QueryFilteredNotes = { + contactId: number | string; + ticketId: number | string; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + + const { ticketNotes, count, hasMore } = await ListTicketNotesService({ + searchParam, + pageNumber + }); + + return res.json({ ticketNotes, count, hasMore }); +}; + +export const list = async (req: Request, res: Response): Promise => { + const ticketNotes: TicketNote[] = await FindAllTicketNotesService(); + + return res.status(200).json(ticketNotes); +}; + +export const store = async (req: Request, res: Response): Promise => { + const newTicketNote: StoreTicketNoteData = req.body; + const { id: userId } = req.user; + + const schema = Yup.object().shape({ + note: Yup.string().required() + }); + + try { + await schema.validate(newTicketNote); + } catch (err) { + throw new AppError(err.message); + } + + const ticketNote = await CreateTicketNoteService({ + ...newTicketNote, + userId + }); + + return res.status(200).json(ticketNote); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const ticketNote = await ShowTicketNoteService(id); + + return res.status(200).json(ticketNote); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const ticketNote: UpdateTicketNoteData = req.body; + + const schema = Yup.object().shape({ + note: Yup.string() + }); + + try { + await schema.validate(ticketNote); + } catch (err) { + throw new AppError(err.message); + } + + const recordUpdated = await UpdateTicketNoteService(ticketNote); + + return res.status(200).json(recordUpdated); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { id } = req.params; + + if (req.user.profile !== "admin") { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + await DeleteTicketNoteService(id); + + return res.status(200).json({ message: "Observação removida" }); +}; + +export const findFilteredList = async ( + req: Request, + res: Response +): Promise => { + try { + const { contactId, ticketId } = req.query as QueryFilteredNotes; + const notes: TicketNote[] = await FindNotesByContactIdAndTicketId({ + contactId, + ticketId + }); + + return res.status(200).json(notes); + } catch (e) { + return res.status(500).json({ message: e }); + } +}; diff --git a/backend/src/controllers/TicketTagController.ts b/backend/src/controllers/TicketTagController.ts new file mode 100644 index 0000000..c240c8b --- /dev/null +++ b/backend/src/controllers/TicketTagController.ts @@ -0,0 +1,57 @@ +import { Request, Response } from "express"; +import AppError from "../errors/AppError"; +import TicketTag from '../models/TicketTag'; +import Tag from '../models/Tag' + +export const store = async (req: Request, res: Response): Promise => { + const { ticketId, tagId } = req.params; + + try { + const ticketTag = await TicketTag.create({ ticketId, tagId }); + return res.status(201).json(ticketTag); + } catch (error) { + return res.status(500).json({ error: 'Failed to store ticket tag.' }); + } +}; + +/* +export const remove = async (req: Request, res: Response): Promise => { + const { ticketId } = req.params; + + + + try { + await TicketTag.destroy({ where: { ticketId } }); + return res.status(200).json({ message: 'Ticket tags removed successfully.' }); + } catch (error) { + return res.status(500).json({ error: 'Failed to remove ticket tags.' }); + } +}; +*/ +export const remove = async (req: Request, res: Response): Promise => { + const { ticketId } = req.params; + + + try { + // Retrieve tagIds associated with the provided ticketId from TicketTags + const ticketTags = await TicketTag.findAll({ where: { ticketId } }); + const tagIds = ticketTags.map((ticketTag) => ticketTag.tagId); + + // Find the tagIds with kanban = 1 in the Tags table + const tagsWithKanbanOne = await Tag.findAll({ + where: { + id: tagIds, + kanban: 1, + }, + }); + + // Remove the tagIds with kanban = 1 from TicketTags + const tagIdsWithKanbanOne = tagsWithKanbanOne.map((tag) => tag.id); + if (tagIdsWithKanbanOne) + await TicketTag.destroy({ where: { ticketId, tagId: tagIdsWithKanbanOne } }); + + return res.status(200).json({ message: 'Ticket tags removed successfully.' }); + } catch (error) { + return res.status(500).json({ error: 'Failed to remove ticket tags.' }); + } +}; diff --git a/backend/src/controllers/UserController.ts b/backend/src/controllers/UserController.ts new file mode 100644 index 0000000..80451e3 --- /dev/null +++ b/backend/src/controllers/UserController.ts @@ -0,0 +1,155 @@ +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; + +import CheckSettingsHelper from "../helpers/CheckSettings"; +import AppError from "../errors/AppError"; + +import CreateUserService from "../services/UserServices/CreateUserService"; +import ListUsersService from "../services/UserServices/ListUsersService"; +import UpdateUserService from "../services/UserServices/UpdateUserService"; +import ShowUserService from "../services/UserServices/ShowUserService"; +import DeleteUserService from "../services/UserServices/DeleteUserService"; +import SimpleListService from "../services/UserServices/SimpleListService"; +import User from "../models/User"; + +type IndexQuery = { + searchParam: string; + pageNumber: string; +}; + +type ListQueryParams = { + companyId: string; +}; + +export const index = async (req: Request, res: Response): Promise => { + const { searchParam, pageNumber } = req.query as IndexQuery; + const { companyId, profile } = req.user; + + const { users, count, hasMore } = await ListUsersService({ + searchParam, + pageNumber, + companyId, + profile + }); + + return res.json({ users, count, hasMore }); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { + email, + password, + name, + profile, + companyId: bodyCompanyId, + queueIds, + whatsappId, + allTicket + } = req.body; + + const whatsappNumber = typeof req.body.whatsappNumber === "string" ? req.body.whatsappNumber.trim() : null; + + let userCompanyId: number | null = null; + let requestUser: User | null = null; + + if (req.user !== undefined) { + const { companyId: cId } = req.user; + userCompanyId = cId; + requestUser = await User.findByPk(req.user.id); + } + + const newUserCompanyId = bodyCompanyId || userCompanyId; + + if (req.url === "/signup") { + if (await CheckSettingsHelper("userCreation") === "disabled") { + throw new AppError("ERR_USER_CREATION_DISABLED", 403); + } + } else if (req.user?.profile !== "admin") { + throw new AppError("ERR_NO_PERMISSION", 403); + } else if (newUserCompanyId !== req.user?.companyId && !requestUser?.super) { + throw new AppError("ERR_NO_SUPER", 403); + } + + const user = await CreateUserService({ + email, + password, + name, + profile, + companyId: newUserCompanyId, + queueIds, + whatsappId, + allTicket, + whatsappNumber + }); + + const io = getIO(); + io.to(`company-${userCompanyId}-mainchannel`).emit(`company-${userCompanyId}-user`, { + action: "create", + user + }); + + return res.status(200).json(user); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { userId } = req.params; + const user = await ShowUserService(userId); + return res.status(200).json(user); +}; + +export const update = async (req: Request, res: Response): Promise => { + const { id: requestUserId, companyId } = req.user; + const { userId } = req.params; + const userData = req.body; + + if (typeof userData.whatsappNumber !== "string") { + userData.whatsappNumber = null; + } else { + userData.whatsappNumber = userData.whatsappNumber.trim(); + } + + const user = await UpdateUserService({ + userData, + userId, + companyId, + requestUserId: +requestUserId + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-user`, { + action: "update", + user + }); + + return res.status(200).json(user); +}; + +export const remove = async (req: Request, res: Response): Promise => { + const { userId } = req.params; + const { companyId } = req.user; + + if (req.user.profile !== "admin") { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + await DeleteUserService(userId, companyId); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-user`, { + action: "delete", + userId + }); + + return res.status(200).json({ message: "User deleted" }); +}; + +export const list = async (req: Request, res: Response): Promise => { + const { companyId } = req.query; + const { companyId: userCompanyId } = req.user; + + const users = await SimpleListService({ + companyId: companyId ? +companyId : userCompanyId + }); + + return res.status(200).json(users); +}; diff --git a/backend/src/controllers/VersionController.ts b/backend/src/controllers/VersionController.ts new file mode 100644 index 0000000..09a8d91 --- /dev/null +++ b/backend/src/controllers/VersionController.ts @@ -0,0 +1,7 @@ +import { Request, Response } from "express"; + +export const index = async (req: Request, res: Response): Promise => { + return res.status(200).json({ + version: "10.12.0" + }); +}; diff --git a/backend/src/controllers/WebhookHubController.ts b/backend/src/controllers/WebhookHubController.ts new file mode 100644 index 0000000..6761dbc --- /dev/null +++ b/backend/src/controllers/WebhookHubController.ts @@ -0,0 +1,28 @@ +import { Request, Response } from "express"; +import Whatsapp from "../models/Whatsapp"; +import HubMessageListener from "../services/HubServices/HubMessageListener"; + +export const listen = async ( + req: Request, + res: Response +): Promise => { + console.log("Webhook received"); + const medias = req.files as Express.Multer.File[]; + const { channelId } = req.params; + + const connection = await Whatsapp.findOne({ + where: { qrcode: channelId } + }); + + if (!connection) { + return res.status(404).json({ message: "Whatsapp channel not found" }); + } + + try { + await HubMessageListener(req.body, connection, medias); + + return res.status(200).json({ message: "Webhook received" }); + } catch (error) { + return res.status(400).json({ message: error }); + } +}; \ No newline at end of file diff --git a/backend/src/controllers/WhatsAppController.ts b/backend/src/controllers/WhatsAppController.ts new file mode 100644 index 0000000..0c3c5a3 --- /dev/null +++ b/backend/src/controllers/WhatsAppController.ts @@ -0,0 +1,185 @@ +import { Request, Response } from "express"; +import { getIO } from "../libs/socket"; +import { removeWbot, restartWbot } from "../libs/wbot"; +import { StartWhatsAppSession } from "../services/WbotServices/StartWhatsAppSession"; + +import CreateWhatsAppService from "../services/WhatsappService/CreateWhatsAppService"; +import DeleteWhatsAppService from "../services/WhatsappService/DeleteWhatsAppService"; +import ListWhatsAppsService from "../services/WhatsappService/ListWhatsAppsService"; +import ShowWhatsAppService from "../services/WhatsappService/ShowWhatsAppService"; +import UpdateWhatsAppService from "../services/WhatsappService/UpdateWhatsAppService"; +import AppError from "../errors/AppError"; + +interface WhatsappData { + name: string; + queueIds: number[]; + companyId: number; + greetingMessage?: string; + complationMessage?: string; + outOfHoursMessage?: string; + ratingMessage?: string; + status?: string; + isDefault?: boolean; + token?: string; + //sendIdQueue?: number; + //timeSendQueue?: number; + transferQueueId?: number; + timeToTransfer?: number; + promptId?: number; + maxUseBotQueues?: number; + timeUseBotQueues?: number; + expiresTicket?: number; + expiresInactiveMessage?: string; +} + +interface QueryParams { + session?: number | string; +} + +export const index = async (req: Request, res: Response): Promise => { + const { companyId } = req.user; + const { session } = req.query as QueryParams; + const whatsapps = await ListWhatsAppsService({ companyId, session }); + + return res.status(200).json(whatsapps); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { + name, + status, + isDefault, + greetingMessage, + complationMessage, + ratingMessage, + outOfHoursMessage, + queueIds, + token, + //timeSendQueue, + //sendIdQueue, + transferQueueId, + timeToTransfer, + promptId, + maxUseBotQueues, + timeUseBotQueues, + expiresTicket, + expiresInactiveMessage + }: WhatsappData = req.body; + const { companyId } = req.user; + + const { whatsapp, oldDefaultWhatsapp } = await CreateWhatsAppService({ + name, + status, + isDefault, + greetingMessage, + complationMessage, + ratingMessage, + outOfHoursMessage, + queueIds, + companyId, + token, + //timeSendQueue, + //sendIdQueue, + transferQueueId, + timeToTransfer, + promptId, + maxUseBotQueues, + timeUseBotQueues, + expiresTicket, + expiresInactiveMessage + }); + + StartWhatsAppSession(whatsapp, companyId); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-whatsapp`, { + action: "update", + whatsapp + }); + + if (oldDefaultWhatsapp) { + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-whatsapp`, { + action: "update", + whatsapp: oldDefaultWhatsapp + }); + } + + return res.status(200).json(whatsapp); +}; + +export const show = async (req: Request, res: Response): Promise => { + const { whatsappId } = req.params; + const { companyId } = req.user; + const { session } = req.query; + + const whatsapp = await ShowWhatsAppService(whatsappId, companyId, session); + + return res.status(200).json(whatsapp); +}; + +export const update = async ( + req: Request, + res: Response +): Promise => { + const { whatsappId } = req.params; + const whatsappData = req.body; + const { companyId } = req.user; + + const { whatsapp, oldDefaultWhatsapp } = await UpdateWhatsAppService({ + whatsappData, + whatsappId, + companyId + }); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-whatsapp`, { + action: "update", + whatsapp + }); + + if (oldDefaultWhatsapp) { + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-whatsapp`, { + action: "update", + whatsapp: oldDefaultWhatsapp + }); + } + + return res.status(200).json(whatsapp); +}; + +export const remove = async ( + req: Request, + res: Response +): Promise => { + const { whatsappId } = req.params; + const { companyId } = req.user; + + await ShowWhatsAppService(whatsappId, companyId); + + await DeleteWhatsAppService(whatsappId); + removeWbot(+whatsappId); + + const io = getIO(); + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-whatsapp`, { + action: "delete", + whatsappId: +whatsappId + }); + + return res.status(200).json({ message: "Whatsapp deleted." }); +}; + + +export const restart = async ( + req: Request, + res: Response +): Promise => { + const { companyId, profile } = req.user; + + if (profile !== "admin") { + throw new AppError("ERR_NO_PERMISSION", 403); + } + + await restartWbot(companyId); + + return res.status(200).json({ message: "Whatsapp restart." }); +}; \ No newline at end of file diff --git a/backend/src/controllers/WhatsAppSessionController.ts b/backend/src/controllers/WhatsAppSessionController.ts new file mode 100644 index 0000000..b56eb42 --- /dev/null +++ b/backend/src/controllers/WhatsAppSessionController.ts @@ -0,0 +1,44 @@ +import { Request, Response } from "express"; +import { getWbot } from "../libs/wbot"; +import ShowWhatsAppService from "../services/WhatsappService/ShowWhatsAppService"; +import { StartWhatsAppSession } from "../services/WbotServices/StartWhatsAppSession"; +import UpdateWhatsAppService from "../services/WhatsappService/UpdateWhatsAppService"; + +const store = async (req: Request, res: Response): Promise => { + const { whatsappId } = req.params; + const { companyId } = req.user; + + const whatsapp = await ShowWhatsAppService(whatsappId, companyId); + await StartWhatsAppSession(whatsapp, companyId); + + return res.status(200).json({ message: "Starting session." }); +}; + +const update = async (req: Request, res: Response): Promise => { + const { whatsappId } = req.params; + const { companyId } = req.user; + + const whatsapp = await ShowWhatsAppService(whatsappId, companyId); + + await whatsapp.update({ session: "" }); + + await StartWhatsAppSession(whatsapp, companyId); + + return res.status(200).json({ message: "Starting session." }); +}; + +const remove = async (req: Request, res: Response): Promise => { + const { whatsappId } = req.params; + const { companyId } = req.user; + const whatsapp = await ShowWhatsAppService(whatsappId, companyId); + + if (whatsapp.session) { + await whatsapp.update({ status: "DISCONNECTED", session: "" }); + const wbot = getWbot(whatsapp.id); + await wbot.logout(); + } + + return res.status(200).json({ message: "Session disconnected." }); +}; + +export default { store, remove, update }; diff --git a/backend/src/database/index.ts b/backend/src/database/index.ts new file mode 100644 index 0000000..998932e --- /dev/null +++ b/backend/src/database/index.ts @@ -0,0 +1,93 @@ +import { Sequelize } from "sequelize-typescript"; +import User from "../models/User"; +import Setting from "../models/Setting"; +import Contact from "../models/Contact"; +import Ticket from "../models/Ticket"; +import Whatsapp from "../models/Whatsapp"; +import ContactCustomField from "../models/ContactCustomField"; +import Message from "../models/Message"; +import Queue from "../models/Queue"; +import WhatsappQueue from "../models/WhatsappQueue"; +import UserQueue from "../models/UserQueue"; +import Company from "../models/Company"; +import Plan from "../models/Plan"; +import TicketNote from "../models/TicketNote"; +import QuickMessage from "../models/QuickMessage"; +import Help from "../models/Help"; +import TicketTraking from "../models/TicketTraking"; +import UserRating from "../models/UserRating"; +import QueueOption from "../models/QueueOption"; +import Schedule from "../models/Schedule"; +import Tag from "../models/Tag"; +import TicketTag from "../models/TicketTag"; +import ContactList from "../models/ContactList"; +import ContactListItem from "../models/ContactListItem"; +import Campaign from "../models/Campaign"; +import CampaignSetting from "../models/CampaignSetting"; +import Baileys from "../models/Baileys"; +import CampaignShipping from "../models/CampaignShipping"; +import Announcement from "../models/Announcement"; +import Chat from "../models/Chat"; +import ChatUser from "../models/ChatUser"; +import ChatMessage from "../models/ChatMessage"; +import Invoices from "../models/Invoices"; +import Subscriptions from "../models/Subscriptions"; +import BaileysChats from "../models/BaileysChats"; +import Files from "../models/Files"; +import FilesOptions from "../models/FilesOptions"; +import Prompt from "../models/Prompt"; +import QueueIntegrations from "../models/QueueIntegrations"; + +// Adicione a importação do modelo HubNotificaMe +import HubNotificaMe from "../models/HubNotificaMe"; + +// eslint-disable-next-line +const dbConfig = require("../config/database"); + +const sequelize = new Sequelize(dbConfig); + +const models = [ + Company, + User, + Contact, + Ticket, + Message, + Whatsapp, + ContactCustomField, + Setting, + Queue, + WhatsappQueue, + UserQueue, + Plan, + TicketNote, + QuickMessage, + Help, + TicketTraking, + UserRating, + QueueOption, + Schedule, + Tag, + TicketTag, + ContactList, + ContactListItem, + Campaign, + CampaignSetting, + Baileys, + CampaignShipping, + Announcement, + Chat, + ChatUser, + ChatMessage, + Invoices, + Subscriptions, + BaileysChats, + Files, + FilesOptions, + Prompt, + QueueIntegrations, + HubNotificaMe, +]; + +sequelize.addModels(models); + +export default sequelize; diff --git a/backend/src/database/migrations/20200717133431-add-uuid-ossp.ts b/backend/src/database/migrations/20200717133431-add-uuid-ossp.ts new file mode 100644 index 0000000..55ffdc5 --- /dev/null +++ b/backend/src/database/migrations/20200717133431-add-uuid-ossp.ts @@ -0,0 +1,10 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.sequelize.query('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"'), + ]); + }, + +}; diff --git a/backend/src/database/migrations/20200717133438-create-users.ts b/backend/src/database/migrations/20200717133438-create-users.ts new file mode 100644 index 0000000..17e9ee9 --- /dev/null +++ b/backend/src/database/migrations/20200717133438-create-users.ts @@ -0,0 +1,39 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Users", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + email: { + type: DataTypes.STRING, + allowNull: false, + unique: true + }, + passwordHash: { + type: DataTypes.STRING, + allowNull: false + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Users"); + } +}; diff --git a/backend/src/database/migrations/20200717144403-create-contacts.ts b/backend/src/database/migrations/20200717144403-create-contacts.ts new file mode 100644 index 0000000..55e4566 --- /dev/null +++ b/backend/src/database/migrations/20200717144403-create-contacts.ts @@ -0,0 +1,45 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Contacts", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + number: { + type: DataTypes.STRING, + allowNull: true + }, + profilePicUrl: { + type: DataTypes.TEXT + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + }, + messengerId: { + type: DataTypes.STRING, + allowNull: true + }, + instagramId: { + type: DataTypes.STRING, + allowNull: true + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Contacts"); + } +}; diff --git a/backend/src/database/migrations/20200717145643-create-tickets.ts b/backend/src/database/migrations/20200717145643-create-tickets.ts new file mode 100644 index 0000000..d5016ee --- /dev/null +++ b/backend/src/database/migrations/20200717145643-create-tickets.ts @@ -0,0 +1,46 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Tickets", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + status: { + type: DataTypes.STRING, + defaultValue: "pending", + allowNull: false + }, + lastMessage: { + type: DataTypes.STRING + }, + contactId: { + type: DataTypes.INTEGER, + references: { model: "Contacts", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE" + }, + userId: { + type: DataTypes.INTEGER, + references: { model: "Users", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }, + createdAt: { + type: DataTypes.DATE(6), + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE(6), + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Tickets"); + } +}; diff --git a/backend/src/database/migrations/20200717151645-create-messages.ts b/backend/src/database/migrations/20200717151645-create-messages.ts new file mode 100644 index 0000000..052dfc1 --- /dev/null +++ b/backend/src/database/migrations/20200717151645-create-messages.ts @@ -0,0 +1,58 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Messages", { + id: { + type: DataTypes.STRING, + primaryKey: true, + allowNull: false + }, + body: { + type: DataTypes.TEXT, + allowNull: false + }, + ack: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + read: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }, + mediaType: { + type: DataTypes.STRING + }, + mediaUrl: { + type: DataTypes.STRING + }, + userId: { + type: DataTypes.INTEGER, + references: { model: "Users", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }, + ticketId: { + type: DataTypes.INTEGER, + references: { model: "Tickets", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + createdAt: { + type: DataTypes.DATE(6), + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE(6), + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Messages"); + } +}; diff --git a/backend/src/database/migrations/20200717170223-create-whatsapps.ts b/backend/src/database/migrations/20200717170223-create-whatsapps.ts new file mode 100644 index 0000000..7e7ec64 --- /dev/null +++ b/backend/src/database/migrations/20200717170223-create-whatsapps.ts @@ -0,0 +1,44 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Whatsapps", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + session: { + type: DataTypes.TEXT + }, + qrcode: { + type: DataTypes.TEXT + }, + status: { + type: DataTypes.STRING + }, + battery: { + type: DataTypes.STRING + }, + plugged: { + type: DataTypes.BOOLEAN + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + }, + type: { + type: DataTypes.STRING + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Whatsapps"); + } +}; diff --git a/backend/src/database/migrations/20200723200315-create-contacts-custom-fields.ts b/backend/src/database/migrations/20200723200315-create-contacts-custom-fields.ts new file mode 100644 index 0000000..c6cc7f7 --- /dev/null +++ b/backend/src/database/migrations/20200723200315-create-contacts-custom-fields.ts @@ -0,0 +1,41 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("ContactCustomFields", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + value: { + type: DataTypes.STRING, + allowNull: false + }, + contactId: { + type: DataTypes.INTEGER, + references: { model: "Contacts", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("ContactCustomFields"); + } +}; diff --git a/backend/src/database/migrations/20200723202116-add-email-field-to-contacts.ts b/backend/src/database/migrations/20200723202116-add-email-field-to-contacts.ts new file mode 100644 index 0000000..cbf086d --- /dev/null +++ b/backend/src/database/migrations/20200723202116-add-email-field-to-contacts.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Contacts", "email", { + type: DataTypes.STRING, + allowNull: false, + defaultValue: "" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Contacts", "email"); + } +}; diff --git a/backend/src/database/migrations/20200730153237-remove-user-association-from-messages.ts b/backend/src/database/migrations/20200730153237-remove-user-association-from-messages.ts new file mode 100644 index 0000000..765619f --- /dev/null +++ b/backend/src/database/migrations/20200730153237-remove-user-association-from-messages.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Messages", "userId"); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Messages", "userId", { + type: DataTypes.INTEGER, + references: { model: "Users", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + } +}; diff --git a/backend/src/database/migrations/20200730153545-add-fromMe-to-messages.ts b/backend/src/database/migrations/20200730153545-add-fromMe-to-messages.ts new file mode 100644 index 0000000..4bdcebe --- /dev/null +++ b/backend/src/database/migrations/20200730153545-add-fromMe-to-messages.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Messages", "fromMe", { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Messages", "fromMe"); + } +}; diff --git a/backend/src/database/migrations/20200813114236-change-ticket-lastMessage-column-type.ts b/backend/src/database/migrations/20200813114236-change-ticket-lastMessage-column-type.ts new file mode 100644 index 0000000..e4248e8 --- /dev/null +++ b/backend/src/database/migrations/20200813114236-change-ticket-lastMessage-column-type.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.changeColumn("Tickets", "lastMessage", { + type: DataTypes.TEXT + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.changeColumn("Tickets", "lastMessage", { + type: DataTypes.STRING + }); + } +}; diff --git a/backend/src/database/migrations/20200901235509-add-profile-column-to-users.ts b/backend/src/database/migrations/20200901235509-add-profile-column-to-users.ts new file mode 100644 index 0000000..b1d866d --- /dev/null +++ b/backend/src/database/migrations/20200901235509-add-profile-column-to-users.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Users", "profile", { + type: DataTypes.STRING, + allowNull: false, + defaultValue: "admin" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Users", "profile"); + } +}; diff --git a/backend/src/database/migrations/20200903215941-create-settings.ts b/backend/src/database/migrations/20200903215941-create-settings.ts new file mode 100644 index 0000000..b8724fc --- /dev/null +++ b/backend/src/database/migrations/20200903215941-create-settings.ts @@ -0,0 +1,29 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Settings", { + key: { + type: DataTypes.STRING, + primaryKey: true, + allowNull: false + }, + value: { + type: DataTypes.TEXT, + allowNull: false + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Settings"); + } +}; diff --git a/backend/src/database/migrations/20200904220257-add-name-to-whatsapp.ts b/backend/src/database/migrations/20200904220257-add-name-to-whatsapp.ts new file mode 100644 index 0000000..3d15507 --- /dev/null +++ b/backend/src/database/migrations/20200904220257-add-name-to-whatsapp.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "name", { + type: DataTypes.STRING, + allowNull: false, + unique: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "name"); + } +}; diff --git a/backend/src/database/migrations/20200906122228-add-name-default-field-to-whatsapp.ts b/backend/src/database/migrations/20200906122228-add-name-default-field-to-whatsapp.ts new file mode 100644 index 0000000..7ec4a50 --- /dev/null +++ b/backend/src/database/migrations/20200906122228-add-name-default-field-to-whatsapp.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "default", { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "default"); + } +}; diff --git a/backend/src/database/migrations/20200906155658-add-whatsapp-field-to-tickets.ts b/backend/src/database/migrations/20200906155658-add-whatsapp-field-to-tickets.ts new file mode 100644 index 0000000..5ed102d --- /dev/null +++ b/backend/src/database/migrations/20200906155658-add-whatsapp-field-to-tickets.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Tickets", "whatsappId", { + type: DataTypes.INTEGER, + references: { model: "Whatsapps", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Tickets", "whatsappId"); + } +}; diff --git a/backend/src/database/migrations/20200919124112-update-default-column-name-on-whatsappp.ts b/backend/src/database/migrations/20200919124112-update-default-column-name-on-whatsappp.ts new file mode 100644 index 0000000..4821129 --- /dev/null +++ b/backend/src/database/migrations/20200919124112-update-default-column-name-on-whatsappp.ts @@ -0,0 +1,11 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.renameColumn("Whatsapps", "default", "isDefault"); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.renameColumn("Whatsapps", "isDefault", "default"); + } +}; diff --git a/backend/src/database/migrations/20200927220708-add-isDeleted-column-to-messages.ts b/backend/src/database/migrations/20200927220708-add-isDeleted-column-to-messages.ts new file mode 100644 index 0000000..a3ffa86 --- /dev/null +++ b/backend/src/database/migrations/20200927220708-add-isDeleted-column-to-messages.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Messages", "isDeleted", { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Messages", "isDeleted"); + } +}; diff --git a/backend/src/database/migrations/20200929145451-add-user-tokenVersion-column.ts b/backend/src/database/migrations/20200929145451-add-user-tokenVersion-column.ts new file mode 100644 index 0000000..ceb5c21 --- /dev/null +++ b/backend/src/database/migrations/20200929145451-add-user-tokenVersion-column.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Users", "tokenVersion", { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Users", "tokenVersion"); + } +}; diff --git a/backend/src/database/migrations/20200930162323-add-isGroup-column-to-tickets.ts b/backend/src/database/migrations/20200930162323-add-isGroup-column-to-tickets.ts new file mode 100644 index 0000000..3e7ba47 --- /dev/null +++ b/backend/src/database/migrations/20200930162323-add-isGroup-column-to-tickets.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Tickets", "isGroup", { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Tickets", "isGroup"); + } +}; diff --git a/backend/src/database/migrations/20200930194808-add-isGroup-column-to-contacts.ts b/backend/src/database/migrations/20200930194808-add-isGroup-column-to-contacts.ts new file mode 100644 index 0000000..d2037ec --- /dev/null +++ b/backend/src/database/migrations/20200930194808-add-isGroup-column-to-contacts.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Contacts", "isGroup", { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Contacts", "isGroup"); + } +}; diff --git a/backend/src/database/migrations/20201004150008-add-contactId-column-to-messages.ts b/backend/src/database/migrations/20201004150008-add-contactId-column-to-messages.ts new file mode 100644 index 0000000..4b8f111 --- /dev/null +++ b/backend/src/database/migrations/20201004150008-add-contactId-column-to-messages.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Messages", "contactId", { + type: DataTypes.INTEGER, + references: { model: "Contacts", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Messages", "contactId"); + } +}; diff --git a/backend/src/database/migrations/20201004155719-add-vcardContactId-column-to-messages.ts b/backend/src/database/migrations/20201004155719-add-vcardContactId-column-to-messages.ts new file mode 100644 index 0000000..d897363 --- /dev/null +++ b/backend/src/database/migrations/20201004155719-add-vcardContactId-column-to-messages.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Messages", "vcardContactId", { + type: DataTypes.INTEGER, + references: { model: "Contacts", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Messages", "vcardContactId"); + } +}; diff --git a/backend/src/database/migrations/20201004955719-remove-vcardContactId-column-to-messages.ts b/backend/src/database/migrations/20201004955719-remove-vcardContactId-column-to-messages.ts new file mode 100644 index 0000000..dac0046 --- /dev/null +++ b/backend/src/database/migrations/20201004955719-remove-vcardContactId-column-to-messages.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Messages", "vcardContactId"); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Messages", "vcardContactId", { + type: DataTypes.INTEGER, + references: { model: "Contacts", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE" + }); + } +}; diff --git a/backend/src/database/migrations/20201026215410-add-retries-to-whatsapps.ts b/backend/src/database/migrations/20201026215410-add-retries-to-whatsapps.ts new file mode 100644 index 0000000..57b1450 --- /dev/null +++ b/backend/src/database/migrations/20201026215410-add-retries-to-whatsapps.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "retries", { + type: DataTypes.INTEGER, + defaultValue: 0, + allowNull: false + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "retries"); + } +}; diff --git a/backend/src/database/migrations/20201028124427-add-quoted-msg-to-messages.ts b/backend/src/database/migrations/20201028124427-add-quoted-msg-to-messages.ts new file mode 100644 index 0000000..8bfd56f --- /dev/null +++ b/backend/src/database/migrations/20201028124427-add-quoted-msg-to-messages.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Messages", "quotedMsgId", { + type: DataTypes.STRING, + references: { model: "Messages", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Messages", "quotedMsgId"); + } +}; diff --git a/backend/src/database/migrations/20210108001431-add-unreadMessages-to-tickets.ts b/backend/src/database/migrations/20210108001431-add-unreadMessages-to-tickets.ts new file mode 100644 index 0000000..ca5b47f --- /dev/null +++ b/backend/src/database/migrations/20210108001431-add-unreadMessages-to-tickets.ts @@ -0,0 +1,13 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Tickets", "unreadMessages", { + type: DataTypes.INTEGER + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Tickets", "unreadMessages"); + } +}; diff --git a/backend/src/database/migrations/20210108164404-create-queues.ts b/backend/src/database/migrations/20210108164404-create-queues.ts new file mode 100644 index 0000000..4a404d6 --- /dev/null +++ b/backend/src/database/migrations/20210108164404-create-queues.ts @@ -0,0 +1,39 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Queues", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + name: { + type: DataTypes.STRING, + allowNull: false, + unique: true + }, + color: { + type: DataTypes.STRING, + allowNull: false, + unique: true + }, + greetingMessage: { + type: DataTypes.TEXT + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Queues"); + } +}; diff --git a/backend/src/database/migrations/20210108164504-add-queueId-to-tickets.ts b/backend/src/database/migrations/20210108164504-add-queueId-to-tickets.ts new file mode 100644 index 0000000..6122b32 --- /dev/null +++ b/backend/src/database/migrations/20210108164504-add-queueId-to-tickets.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Tickets", "queueId", { + type: DataTypes.INTEGER, + references: { model: "Queues", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Tickets", "queueId"); + } +}; diff --git a/backend/src/database/migrations/20210108174594-associate-whatsapp-queue.ts b/backend/src/database/migrations/20210108174594-associate-whatsapp-queue.ts new file mode 100644 index 0000000..0e08f71 --- /dev/null +++ b/backend/src/database/migrations/20210108174594-associate-whatsapp-queue.ts @@ -0,0 +1,28 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("WhatsappQueues", { + whatsappId: { + type: DataTypes.INTEGER, + primaryKey: true + }, + queueId: { + type: DataTypes.INTEGER, + primaryKey: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("WhatsappQueues"); + } +}; diff --git a/backend/src/database/migrations/20210108204708-associate-users-queue.ts b/backend/src/database/migrations/20210108204708-associate-users-queue.ts new file mode 100644 index 0000000..d92496a --- /dev/null +++ b/backend/src/database/migrations/20210108204708-associate-users-queue.ts @@ -0,0 +1,28 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("UserQueues", { + userId: { + type: DataTypes.INTEGER, + primaryKey: true + }, + queueId: { + type: DataTypes.INTEGER, + primaryKey: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("UserQueues"); + } +}; diff --git a/backend/src/database/migrations/20210109192513-add-greetingMessage-to-whatsapp.ts b/backend/src/database/migrations/20210109192513-add-greetingMessage-to-whatsapp.ts new file mode 100644 index 0000000..6d3c3be --- /dev/null +++ b/backend/src/database/migrations/20210109192513-add-greetingMessage-to-whatsapp.ts @@ -0,0 +1,13 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "greetingMessage", { + type: DataTypes.TEXT + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "greetingMessage"); + } +}; diff --git a/backend/src/database/migrations/20210109192514-create-companies-table.ts b/backend/src/database/migrations/20210109192514-create-companies-table.ts new file mode 100644 index 0000000..773c786 --- /dev/null +++ b/backend/src/database/migrations/20210109192514-create-companies-table.ts @@ -0,0 +1,39 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Companies", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + name: { + type: DataTypes.STRING, + allowNull: false, + unique: true + }, + phone: { + type: DataTypes.STRING, + allowNull: true + }, + email: { + type: DataTypes.STRING, + allowNull: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Companies"); + } +}; diff --git a/backend/src/database/migrations/20210109192515-add-column-companyId-to-Settings-table.ts b/backend/src/database/migrations/20210109192515-add-column-companyId-to-Settings-table.ts new file mode 100644 index 0000000..7ae9017 --- /dev/null +++ b/backend/src/database/migrations/20210109192515-add-column-companyId-to-Settings-table.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Settings", "companyId", { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Settings", "companyId"); + } +}; diff --git a/backend/src/database/migrations/20210109192516-add-column-companyId-to-Users-table.ts b/backend/src/database/migrations/20210109192516-add-column-companyId-to-Users-table.ts new file mode 100644 index 0000000..885dc8a --- /dev/null +++ b/backend/src/database/migrations/20210109192516-add-column-companyId-to-Users-table.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Users", "companyId", { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Users", "companyId"); + } +}; diff --git a/backend/src/database/migrations/20210109192517-add-column-companyId-to-Contacts-table.ts b/backend/src/database/migrations/20210109192517-add-column-companyId-to-Contacts-table.ts new file mode 100644 index 0000000..d348602 --- /dev/null +++ b/backend/src/database/migrations/20210109192517-add-column-companyId-to-Contacts-table.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Contacts", "companyId", { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Contacts", "companyId"); + } +}; diff --git a/backend/src/database/migrations/20210109192518-add-column-companyId-to-Messages-table.ts b/backend/src/database/migrations/20210109192518-add-column-companyId-to-Messages-table.ts new file mode 100644 index 0000000..fb1d711 --- /dev/null +++ b/backend/src/database/migrations/20210109192518-add-column-companyId-to-Messages-table.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Messages", "companyId", { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Messages", "companyId"); + } +}; diff --git a/backend/src/database/migrations/20210109192519-add-column-companyId-to-Queues-table.ts b/backend/src/database/migrations/20210109192519-add-column-companyId-to-Queues-table.ts new file mode 100644 index 0000000..02dee46 --- /dev/null +++ b/backend/src/database/migrations/20210109192519-add-column-companyId-to-Queues-table.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Queues", "companyId", { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Queues", "companyId"); + } +}; diff --git a/backend/src/database/migrations/20210109192520-add-column-companyId-to-Whatsapps-table.ts b/backend/src/database/migrations/20210109192520-add-column-companyId-to-Whatsapps-table.ts new file mode 100644 index 0000000..8628328 --- /dev/null +++ b/backend/src/database/migrations/20210109192520-add-column-companyId-to-Whatsapps-table.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "companyId", { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "companyId"); + } +}; diff --git a/backend/src/database/migrations/20210109192521-add-column-companyId-to-Tickets-table.ts b/backend/src/database/migrations/20210109192521-add-column-companyId-to-Tickets-table.ts new file mode 100644 index 0000000..d7ac711 --- /dev/null +++ b/backend/src/database/migrations/20210109192521-add-column-companyId-to-Tickets-table.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Tickets", "companyId", { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Tickets", "companyId"); + } +}; diff --git a/backend/src/database/migrations/20210109192522-create-plans-table.ts b/backend/src/database/migrations/20210109192522-create-plans-table.ts new file mode 100644 index 0000000..96c3e5f --- /dev/null +++ b/backend/src/database/migrations/20210109192522-create-plans-table.ts @@ -0,0 +1,47 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Plans", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + name: { + type: DataTypes.STRING, + allowNull: false, + unique: true + }, + users: { + type: DataTypes.INTEGER, + defaultValue: 0 + }, + connections: { + type: DataTypes.INTEGER, + defaultValue: 0 + }, + queues: { + type: DataTypes.INTEGER, + defaultValue: 0 + }, + value: { + type: DataTypes.FLOAT, + defaultValue: 0 + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Plans"); + } +}; diff --git a/backend/src/database/migrations/20210109192523-add-column-planId-to-Companies.ts b/backend/src/database/migrations/20210109192523-add-column-planId-to-Companies.ts new file mode 100644 index 0000000..020ffe8 --- /dev/null +++ b/backend/src/database/migrations/20210109192523-add-column-planId-to-Companies.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Companies", "planId", { + type: DataTypes.INTEGER, + references: { model: "Plans", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Companies", "planId"); + } +}; diff --git a/backend/src/database/migrations/20210109192523-add-column-status-and-schedules-to-Companies.ts b/backend/src/database/migrations/20210109192523-add-column-status-and-schedules-to-Companies.ts new file mode 100644 index 0000000..c9bbe71 --- /dev/null +++ b/backend/src/database/migrations/20210109192523-add-column-status-and-schedules-to-Companies.ts @@ -0,0 +1,23 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.addColumn("Companies", "status", { + type: DataTypes.BOOLEAN, + defaultValue: true + }), + queryInterface.addColumn("Companies", "schedules", { + type: DataTypes.JSONB, + defaultValue: [] + }) + ]); + }, + + down: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.removeColumn("Companies", "schedules"), + queryInterface.removeColumn("Companies", "status") + ]); + } +}; diff --git a/backend/src/database/migrations/20210109192523-create-ticket-notes.ts b/backend/src/database/migrations/20210109192523-create-ticket-notes.ts new file mode 100644 index 0000000..2163d5e --- /dev/null +++ b/backend/src/database/migrations/20210109192523-create-ticket-notes.ts @@ -0,0 +1,49 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("TicketNotes", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + note: { + type: DataTypes.STRING, + allowNull: false + }, + userId: { + type: DataTypes.INTEGER, + references: { model: "Users", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }, + contactId: { + type: DataTypes.INTEGER, + references: { model: "Contacts", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + ticketId: { + type: DataTypes.INTEGER, + references: { model: "Tickets", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Plans"); + } +}; diff --git a/backend/src/database/migrations/20210109192524-create-quick-messages.ts b/backend/src/database/migrations/20210109192524-create-quick-messages.ts new file mode 100644 index 0000000..c390b6d --- /dev/null +++ b/backend/src/database/migrations/20210109192524-create-quick-messages.ts @@ -0,0 +1,40 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("QuickMessages", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + shortcode: { + type: DataTypes.STRING, + allowNull: false + }, + message: { + type: DataTypes.STRING, + allowNull: false + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE" + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("QuickMessages"); + } +}; diff --git a/backend/src/database/migrations/20210109192525-add-column-complationMessage-to-whatsapp.ts b/backend/src/database/migrations/20210109192525-add-column-complationMessage-to-whatsapp.ts new file mode 100644 index 0000000..a3bfb4f --- /dev/null +++ b/backend/src/database/migrations/20210109192525-add-column-complationMessage-to-whatsapp.ts @@ -0,0 +1,13 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "complationMessage", { + type: DataTypes.TEXT + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "complationMessage"); + } +}; diff --git a/backend/src/database/migrations/20210109192526-add-column-outOfHoursMessage-to-whatsapp .ts b/backend/src/database/migrations/20210109192526-add-column-outOfHoursMessage-to-whatsapp .ts new file mode 100644 index 0000000..c9f4589 --- /dev/null +++ b/backend/src/database/migrations/20210109192526-add-column-outOfHoursMessage-to-whatsapp .ts @@ -0,0 +1,13 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "outOfHoursMessage", { + type: DataTypes.TEXT + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "outOfHoursMessage"); + } +}; diff --git a/backend/src/database/migrations/20210109192527-add-column-super-to-Users-table.ts b/backend/src/database/migrations/20210109192527-add-column-super-to-Users-table.ts new file mode 100644 index 0000000..5a5a3b3 --- /dev/null +++ b/backend/src/database/migrations/20210109192527-add-column-super-to-Users-table.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Users", "super", { + type: DataTypes.BOOLEAN, + defaultValue: false + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Users", "super"); + } +}; diff --git a/backend/src/database/migrations/20210109192528-change-column-message-to-quick-messages-table.ts b/backend/src/database/migrations/20210109192528-change-column-message-to-quick-messages-table.ts new file mode 100644 index 0000000..852cc57 --- /dev/null +++ b/backend/src/database/migrations/20210109192528-change-column-message-to-quick-messages-table.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.changeColumn("QuickMessages", "message", { + type: DataTypes.TEXT + }); + }, + down: (queryInterface: QueryInterface) => { + return queryInterface.changeColumn("QuickMessages", "message", { + type: DataTypes.STRING + }); + } +}; diff --git a/backend/src/database/migrations/20210109192529-create-helps.ts b/backend/src/database/migrations/20210109192529-create-helps.ts new file mode 100644 index 0000000..ebec49b --- /dev/null +++ b/backend/src/database/migrations/20210109192529-create-helps.ts @@ -0,0 +1,42 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Helps", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + title: { + type: DataTypes.STRING, + allowNull: false + }, + description: { + type: DataTypes.TEXT, + allowNull: true + }, + video: { + type: DataTypes.STRING, + allowNull: true + }, + link: { + type: DataTypes.TEXT, + allowNull: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Helps"); + } +}; diff --git a/backend/src/database/migrations/20210109192530-add-unique-constraint-to-Contacts-table.ts b/backend/src/database/migrations/20210109192530-add-unique-constraint-to-Contacts-table.ts new file mode 100644 index 0000000..32c9fcf --- /dev/null +++ b/backend/src/database/migrations/20210109192530-add-unique-constraint-to-Contacts-table.ts @@ -0,0 +1,17 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addConstraint("Contacts", ["number", "companyId"], { + type: "unique", + name: "number_companyid_unique" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeConstraint( + "Contacts", + "number_companyid_unique" + ); + } +}; diff --git a/backend/src/database/migrations/20210109192531-create-TicketTracking-table.ts b/backend/src/database/migrations/20210109192531-create-TicketTracking-table.ts new file mode 100644 index 0000000..e0f12c1 --- /dev/null +++ b/backend/src/database/migrations/20210109192531-create-TicketTracking-table.ts @@ -0,0 +1,60 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("TicketTraking", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + ticketId: { + type: DataTypes.INTEGER, + references: { model: "Tickets", key: "id" }, + onDelete: "SET NULL" + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onDelete: "SET NULL" + }, + whatsappId: { + type: DataTypes.INTEGER, + references: { model: "Whatsapps", key: "id" }, + onDelete: "SET NULL", + allowNull: true + }, + userId: { + type: DataTypes.INTEGER, + references: { model: "Users", key: "id" }, + onDelete: "SET NULL", + allowNull: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: true + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: true + }, + queuedAt: { + type: DataTypes.DATE, + allowNull: true + }, + startedAt: { + type: DataTypes.DATE, + allowNull: true + }, + finishedAt: { + type: DataTypes.DATE, + allowNull: true + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("TicketTraking"); + } +}; diff --git a/backend/src/database/migrations/20210109192532-add-column-online-to-Users-table.ts b/backend/src/database/migrations/20210109192532-add-column-online-to-Users-table.ts new file mode 100644 index 0000000..c7aafca --- /dev/null +++ b/backend/src/database/migrations/20210109192532-add-column-online-to-Users-table.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Users", "online", { + type: DataTypes.BOOLEAN, + defaultValue: false + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Users", "online"); + } +}; diff --git a/backend/src/database/migrations/20210109192533-create-UserRatings-table.ts b/backend/src/database/migrations/20210109192533-create-UserRatings-table.ts new file mode 100644 index 0000000..91cd5f2 --- /dev/null +++ b/backend/src/database/migrations/20210109192533-create-UserRatings-table.ts @@ -0,0 +1,46 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("UserRatings", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + ticketId: { + type: DataTypes.INTEGER, + references: { model: "Tickets", key: "id" }, + onDelete: "SET NULL" + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onDelete: "SET NULL" + }, + userId: { + type: DataTypes.INTEGER, + references: { model: "Users", key: "id" }, + onDelete: "SET NULL", + allowNull: true + }, + rate: { + type: DataTypes.INTEGER, + defaultValue: 0 + }, + createdAt: { + type: DataTypes.DATE, + allowNull: true + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: true + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("UserRatings"); + } +}; diff --git a/backend/src/database/migrations/20210109192534-add-rated-to-TicketTraking.ts b/backend/src/database/migrations/20210109192534-add-rated-to-TicketTraking.ts new file mode 100644 index 0000000..bc007b1 --- /dev/null +++ b/backend/src/database/migrations/20210109192534-add-rated-to-TicketTraking.ts @@ -0,0 +1,24 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.addColumn("TicketTraking", "ratingAt", { + type: DataTypes.DATE, + allowNull: true, + defaultValue: null + }), + queryInterface.addColumn("TicketTraking", "rated", { + type: DataTypes.BOOLEAN, + defaultValue: false + }) + ]); + }, + + down: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.removeColumn("TicketTraking", "ratingAt"), + queryInterface.removeColumn("TicketTraking", "rated") + ]); + } +}; diff --git a/backend/src/database/migrations/20210109192535-add-column-ratingMessage-to-whatsapp.ts b/backend/src/database/migrations/20210109192535-add-column-ratingMessage-to-whatsapp.ts new file mode 100644 index 0000000..7cfbb4a --- /dev/null +++ b/backend/src/database/migrations/20210109192535-add-column-ratingMessage-to-whatsapp.ts @@ -0,0 +1,13 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "ratingMessage", { + type: DataTypes.TEXT + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "ratingMessage"); + } +}; diff --git a/backend/src/database/migrations/20210818102606-add-uuid-to-tickets.ts b/backend/src/database/migrations/20210818102606-add-uuid-to-tickets.ts new file mode 100644 index 0000000..90669b9 --- /dev/null +++ b/backend/src/database/migrations/20210818102606-add-uuid-to-tickets.ts @@ -0,0 +1,17 @@ +import { QueryInterface, DataTypes, Sequelize } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.addColumn("Tickets", "uuid", { + type: DataTypes.UUID, + allowNull: true, + defaultValue: Sequelize.literal('uuid_generate_v4()') + }) + ]); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Tickets", "uuid"); + } +}; diff --git a/backend/src/database/migrations/20210818102607-remove-unique-indexes-to-Queues-table.ts b/backend/src/database/migrations/20210818102607-remove-unique-indexes-to-Queues-table.ts new file mode 100644 index 0000000..c6087c8 --- /dev/null +++ b/backend/src/database/migrations/20210818102607-remove-unique-indexes-to-Queues-table.ts @@ -0,0 +1,25 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.removeConstraint("Queues", "Queues_color_key"), + queryInterface.removeConstraint("Queues", "Queues_name_key"), + queryInterface.removeIndex("Queues", "Queues_color_key"), + queryInterface.removeIndex("Queues", "Queues_name_key"), + ]); + }, + + down: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.addConstraint("Queues", ["color"], { + name: "Queues_color_key", + type: 'unique' + }), + queryInterface.addConstraint("Queues", ["name"], { + name: "Queues_name_key", + type: 'unique' + }), + ]); + } +}; diff --git a/backend/src/database/migrations/20210818102608-add-unique-indexes-to-Queues-table.ts b/backend/src/database/migrations/20210818102608-add-unique-indexes-to-Queues-table.ts new file mode 100644 index 0000000..9a68704 --- /dev/null +++ b/backend/src/database/migrations/20210818102608-add-unique-indexes-to-Queues-table.ts @@ -0,0 +1,23 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.addConstraint("Queues", ["color", "companyId"], { + name: "Queues_color_key", + type: 'unique' + }), + queryInterface.addConstraint("Queues", ["name", "companyId"], { + name: "Queues_name_key", + type: 'unique' + }), + ]); + }, + + down: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.removeConstraint("Queues", "Queues_color_key"), + queryInterface.removeConstraint("Queues", "Queues_name_key"), + ]); + } +}; diff --git a/backend/src/database/migrations/20210818102609-add-token-to-Whatsapps.ts b/backend/src/database/migrations/20210818102609-add-token-to-Whatsapps.ts new file mode 100644 index 0000000..b17c96f --- /dev/null +++ b/backend/src/database/migrations/20210818102609-add-token-to-Whatsapps.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "token", { + type: DataTypes.TEXT, + allowNull: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "token"); + } +}; diff --git a/backend/src/database/migrations/20211205164404-create-queue-options.ts b/backend/src/database/migrations/20211205164404-create-queue-options.ts new file mode 100644 index 0000000..2009ca9 --- /dev/null +++ b/backend/src/database/migrations/20211205164404-create-queue-options.ts @@ -0,0 +1,51 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("QueueOptions", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + title: { + type: DataTypes.STRING, + allowNull: false, + }, + message: { + type: DataTypes.TEXT, + allowNull: true, + }, + option: { + type: DataTypes.TEXT, + allowNull: true, + }, + queueId: { + type: DataTypes.INTEGER, + references: { model: "Queues", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE" + }, + parentId: { + type: DataTypes.INTEGER, + references: { model: "QueueOptions", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("QueueOptions"); + } +}; diff --git a/backend/src/database/migrations/20211212125704-add-chatbot-to-tickets.ts b/backend/src/database/migrations/20211212125704-add-chatbot-to-tickets.ts new file mode 100644 index 0000000..a1cdc94 --- /dev/null +++ b/backend/src/database/migrations/20211212125704-add-chatbot-to-tickets.ts @@ -0,0 +1,24 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.addColumn("Tickets", "chatbot", { + type: DataTypes.BOOLEAN, + allowNull: true, + defaultValue: false + }), + queryInterface.addColumn("Tickets", "queueOptionId", { + type: DataTypes.INTEGER, + references: { model: "QueueOptions", key: "id" }, + onUpdate: "SET null", + onDelete: "SET null", + allowNull: true + }) + ]); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Tickets", "chatbot"); + } +}; diff --git a/backend/src/database/migrations/20211227010200-create-schedules.ts b/backend/src/database/migrations/20211227010200-create-schedules.ts new file mode 100644 index 0000000..9ae2731 --- /dev/null +++ b/backend/src/database/migrations/20211227010200-create-schedules.ts @@ -0,0 +1,66 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Schedules", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + body: { + type: DataTypes.TEXT, + allowNull: false + }, + sendAt: { + type: DataTypes.DATE, + allowNull: true + }, + sentAt: { + type: DataTypes.DATE, + allowNull: true + }, + contactId: { + type: DataTypes.INTEGER, + references: { model: "Contacts", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: true + }, + ticketId: { + type: DataTypes.INTEGER, + references: { model: "Tickets", key: "id" }, + onUpdate: "SET NULL", + onDelete: "SET NULL", + allowNull: true + }, + userId: { + type: DataTypes.INTEGER, + references: { model: "Users", key: "id" }, + onUpdate: "SET NULL", + onDelete: "SET NULL", + allowNull: true + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Schedules"); + } +}; diff --git a/backend/src/database/migrations/20220115114088-add-column-userId-to-QuickMessages-table.ts b/backend/src/database/migrations/20220115114088-add-column-userId-to-QuickMessages-table.ts new file mode 100644 index 0000000..22f33ed --- /dev/null +++ b/backend/src/database/migrations/20220115114088-add-column-userId-to-QuickMessages-table.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("QuickMessages", "userId", { + type: DataTypes.INTEGER, + references: { model: "Users", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("QuickMessages", "userId"); + } +}; diff --git a/backend/src/database/migrations/20220117130000-create-tags.ts b/backend/src/database/migrations/20220117130000-create-tags.ts new file mode 100644 index 0000000..37870ff --- /dev/null +++ b/backend/src/database/migrations/20220117130000-create-tags.ts @@ -0,0 +1,41 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Tags", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + color: { + type: DataTypes.STRING, + allowNull: true + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Tags"); + } +}; diff --git a/backend/src/database/migrations/20220117134400-associate-tickets-tags.ts b/backend/src/database/migrations/20220117134400-associate-tickets-tags.ts new file mode 100644 index 0000000..6df85cb --- /dev/null +++ b/backend/src/database/migrations/20220117134400-associate-tickets-tags.ts @@ -0,0 +1,34 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("TicketTags", { + ticketId: { + type: DataTypes.INTEGER, + references: { model: "Tickets", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + tagId: { + type: DataTypes.INTEGER, + references: { model: "Tags", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("TicketTags"); + } +}; diff --git a/backend/src/database/migrations/20220122160900-add-status-to-schedules.ts b/backend/src/database/migrations/20220122160900-add-status-to-schedules.ts new file mode 100644 index 0000000..15639d7 --- /dev/null +++ b/backend/src/database/migrations/20220122160900-add-status-to-schedules.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Schedules", "status", { + type: DataTypes.STRING, + allowNull: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Schedules", "status"); + } +}; diff --git a/backend/src/database/migrations/20220220014719-add-farewellMessage-to-whatsapp.ts b/backend/src/database/migrations/20220220014719-add-farewellMessage-to-whatsapp.ts new file mode 100644 index 0000000..40120bf --- /dev/null +++ b/backend/src/database/migrations/20220220014719-add-farewellMessage-to-whatsapp.ts @@ -0,0 +1,13 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "farewellMessage", { + type: DataTypes.TEXT + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "farewellMessage"); + } +}; diff --git a/backend/src/database/migrations/20220221014717-add-provider-whatsapp.ts b/backend/src/database/migrations/20220221014717-add-provider-whatsapp.ts new file mode 100644 index 0000000..263a1a3 --- /dev/null +++ b/backend/src/database/migrations/20220221014717-add-provider-whatsapp.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "provider", { + type: DataTypes.TEXT, + defaultValue: "stable" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "provider"); + } +}; diff --git a/backend/src/database/migrations/20220221014718-add-remoteJid-messages.ts b/backend/src/database/migrations/20220221014718-add-remoteJid-messages.ts new file mode 100644 index 0000000..fd911ad --- /dev/null +++ b/backend/src/database/migrations/20220221014718-add-remoteJid-messages.ts @@ -0,0 +1,13 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Messages", "remoteJid", { + type: DataTypes.TEXT + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Messages", "remoteJid"); + } +}; diff --git a/backend/src/database/migrations/20220221014719-add-jsonMessage-messages.ts b/backend/src/database/migrations/20220221014719-add-jsonMessage-messages.ts new file mode 100644 index 0000000..72f23a6 --- /dev/null +++ b/backend/src/database/migrations/20220221014719-add-jsonMessage-messages.ts @@ -0,0 +1,13 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Messages", "dataJson", { + type: DataTypes.TEXT + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Messages", "dataJson"); + } +}; diff --git a/backend/src/database/migrations/20220221014720-add-participant-messages.ts b/backend/src/database/migrations/20220221014720-add-participant-messages.ts new file mode 100644 index 0000000..65fe5a1 --- /dev/null +++ b/backend/src/database/migrations/20220221014720-add-participant-messages.ts @@ -0,0 +1,13 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Messages", "participant", { + type: DataTypes.TEXT + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Messages", "participant"); + } +}; diff --git a/backend/src/database/migrations/20220221014721-create-baileys.ts b/backend/src/database/migrations/20220221014721-create-baileys.ts new file mode 100644 index 0000000..4544385 --- /dev/null +++ b/backend/src/database/migrations/20220221014721-create-baileys.ts @@ -0,0 +1,38 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Baileys", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + whatsappId: { + type: DataTypes.INTEGER, + primaryKey: true + }, + contacts: { + type: DataTypes.TEXT, + allowNull: true + }, + chats: { + type: DataTypes.TEXT, + allowNull: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Baileys"); + } +}; diff --git a/backend/src/database/migrations/20220315110000-create-ContactLists-table.ts b/backend/src/database/migrations/20220315110000-create-ContactLists-table.ts new file mode 100644 index 0000000..7406ef2 --- /dev/null +++ b/backend/src/database/migrations/20220315110000-create-ContactLists-table.ts @@ -0,0 +1,37 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("ContactLists", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("ContactLists"); + } +}; diff --git a/backend/src/database/migrations/20220315110001-create-ContactListItems-table.ts b/backend/src/database/migrations/20220315110001-create-ContactListItems-table.ts new file mode 100644 index 0000000..009f7a9 --- /dev/null +++ b/backend/src/database/migrations/20220315110001-create-ContactListItems-table.ts @@ -0,0 +1,56 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("ContactListItems", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + number: { + type: DataTypes.STRING, + allowNull: false + }, + email: { + type: DataTypes.STRING, + allowNull: true + }, + contactListId: { + type: DataTypes.INTEGER, + references: { model: "ContactLists", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + isWhatsappValid: { + type: DataTypes.BOOLEAN, + defaultValue: false + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("ContactListItems"); + } +}; diff --git a/backend/src/database/migrations/20220315110002-create-Campaigns-table.ts b/backend/src/database/migrations/20220315110002-create-Campaigns-table.ts new file mode 100644 index 0000000..2d1f568 --- /dev/null +++ b/backend/src/database/migrations/20220315110002-create-Campaigns-table.ts @@ -0,0 +1,126 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Campaigns", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + message1: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: "" + }, + message2: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: "" + }, + message3: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: "" + }, + message4: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: "" + }, + message5: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: "" + }, + confirmationMessage1: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: "" + }, + confirmationMessage2: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: "" + }, + confirmationMessage3: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: "" + }, + confirmationMessage4: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: "" + }, + confirmationMessage5: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: "" + }, + status: { + type: DataTypes.STRING, + allowNull: true + }, + confirmation: { + type: DataTypes.BOOLEAN, + allowNull: true, + defaultValue: false + }, + mediaPath: { + type: DataTypes.TEXT, + allowNull: true + }, + mediaName: { + type: DataTypes.TEXT, + allowNull: true + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + contactListId: { + type: DataTypes.INTEGER, + references: { model: "ContactLists", key: "id" }, + onUpdate: "SET NULL", + onDelete: "SET NULL", + allowNull: true + }, + whatsappId: { + type: DataTypes.INTEGER, + references: { model: "Whatsapps", key: "id" }, + onUpdate: "SET NULL", + onDelete: "SET NULL", + allowNull: true + }, + scheduledAt: { + type: DataTypes.DATE, + allowNull: true + }, + completedAt: { + type: DataTypes.DATE, + allowNull: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Campaigns"); + } +}; diff --git a/backend/src/database/migrations/20220315110004-create-CampaignSettings-table.ts b/backend/src/database/migrations/20220315110004-create-CampaignSettings-table.ts new file mode 100644 index 0000000..4d796a9 --- /dev/null +++ b/backend/src/database/migrations/20220315110004-create-CampaignSettings-table.ts @@ -0,0 +1,41 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("CampaignSettings", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + key: { + type: DataTypes.STRING, + allowNull: false + }, + value: { + type: DataTypes.TEXT, + allowNull: true + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("CampaignSettings"); + } +}; diff --git a/backend/src/database/migrations/20220315110005-remove-constraint-to-Settings.ts b/backend/src/database/migrations/20220315110005-remove-constraint-to-Settings.ts new file mode 100644 index 0000000..f794a99 --- /dev/null +++ b/backend/src/database/migrations/20220315110005-remove-constraint-to-Settings.ts @@ -0,0 +1,27 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.sequelize.query('DELETE FROM "Settings"'), + queryInterface.removeConstraint("Settings", "Settings_pkey"), + queryInterface.addColumn("Settings", "id", { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }) + ]); + }, + + down: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.sequelize.query('DELETE FROM "Settings"'), + queryInterface.removeColumn("Settings", "id"), + queryInterface.addConstraint("Settings", ["key"], { + type: "primary key", + name: "Settings_pkey" + }) + ]); + } +}; diff --git a/backend/src/database/migrations/20220321130000-create-CampaignShipping.ts b/backend/src/database/migrations/20220321130000-create-CampaignShipping.ts new file mode 100644 index 0000000..6570474 --- /dev/null +++ b/backend/src/database/migrations/20220321130000-create-CampaignShipping.ts @@ -0,0 +1,72 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("CampaignShipping", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + jobId: { + type: DataTypes.STRING, + allowNull: true + }, + number: { + type: DataTypes.STRING, + allowNull: false + }, + message: { + type: DataTypes.TEXT, + allowNull: false + }, + confirmationMessage: { + type: DataTypes.TEXT, + allowNull: true + }, + confirmation: { + type: DataTypes.BOOLEAN, + allowNull: true + }, + contactId: { + type: DataTypes.INTEGER, + references: { model: "ContactListItems", key: "id" }, + onUpdate: "SET NULL", + onDelete: "SET NULL", + allowNull: true + }, + campaignId: { + type: DataTypes.INTEGER, + references: { model: "Campaigns", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + confirmationRequestedAt: { + type: DataTypes.DATE, + allowNull: true + }, + confirmedAt: { + type: DataTypes.DATE, + allowNull: true + }, + deliveredAt: { + type: DataTypes.DATE, + allowNull: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("CampaignShipping"); + } +}; diff --git a/backend/src/database/migrations/20220404000000-add-column-queueId-to-Messages-table.ts b/backend/src/database/migrations/20220404000000-add-column-queueId-to-Messages-table.ts new file mode 100644 index 0000000..fc663a1 --- /dev/null +++ b/backend/src/database/migrations/20220404000000-add-column-queueId-to-Messages-table.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Messages", "queueId", { + type: DataTypes.INTEGER, + references: { model: "Queues", key: "id" }, + onUpdate: "SET NULL", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Messages", "queueId"); + } +}; diff --git a/backend/src/database/migrations/20220406000000-add-column-dueDate-to-Companies.ts b/backend/src/database/migrations/20220406000000-add-column-dueDate-to-Companies.ts new file mode 100644 index 0000000..e5083c7 --- /dev/null +++ b/backend/src/database/migrations/20220406000000-add-column-dueDate-to-Companies.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Companies", "dueDate", { + type: DataTypes.DATE, + allowNull: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Companies", "dueDate"); + } +}; diff --git a/backend/src/database/migrations/20220406000001-add-column-recurrence-to-Companies.ts b/backend/src/database/migrations/20220406000001-add-column-recurrence-to-Companies.ts new file mode 100644 index 0000000..09d8760 --- /dev/null +++ b/backend/src/database/migrations/20220406000001-add-column-recurrence-to-Companies.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Companies", "recurrence", { + type: DataTypes.STRING, + allowNull: true, + defaultValue: "" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Companies", "recurrence"); + } +}; diff --git a/backend/src/database/migrations/20220411000000-add-column-startTime-and-endTime-to-Queues.ts b/backend/src/database/migrations/20220411000000-add-column-startTime-and-endTime-to-Queues.ts new file mode 100644 index 0000000..a90dba1 --- /dev/null +++ b/backend/src/database/migrations/20220411000000-add-column-startTime-and-endTime-to-Queues.ts @@ -0,0 +1,28 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.addColumn("Queues", "startTime", { + type: DataTypes.STRING, + defaultValue: null + }), + queryInterface.addColumn("Queues", "endTime", { + type: DataTypes.STRING, + defaultValue: null + }), + queryInterface.addColumn("Queues", "outOfHoursMessage", { + type: DataTypes.TEXT, + defaultValue: null + }) + ]); + }, + + down: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.removeColumn("Queues", "startTime"), + queryInterface.removeColumn("Queues", "endTime"), + queryInterface.removeColumn("Queues", "outOfHoursMessage") + ]); + } +}; diff --git a/backend/src/database/migrations/20220411000001-remove-column-startTime-and-endTime-to-Queues.ts b/backend/src/database/migrations/20220411000001-remove-column-startTime-and-endTime-to-Queues.ts new file mode 100644 index 0000000..7f005b7 --- /dev/null +++ b/backend/src/database/migrations/20220411000001-remove-column-startTime-and-endTime-to-Queues.ts @@ -0,0 +1,28 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.removeColumn("Queues", "startTime"), + queryInterface.removeColumn("Queues", "endTime"), + queryInterface.removeColumn("Queues", "outOfHoursMessage") + ]); + }, + + down: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.addColumn("Queues", "startTime", { + type: DataTypes.STRING, + defaultValue: null + }), + queryInterface.addColumn("Queues", "endTime", { + type: DataTypes.STRING, + defaultValue: null + }), + queryInterface.addColumn("Queues", "outOfHoursMessage", { + type: DataTypes.TEXT, + defaultValue: null + }) + ]); + } +}; diff --git a/backend/src/database/migrations/20220411000002-add-column-schedules-and-outOfHoursMessage-to-Queues.ts b/backend/src/database/migrations/20220411000002-add-column-schedules-and-outOfHoursMessage-to-Queues.ts new file mode 100644 index 0000000..72023d0 --- /dev/null +++ b/backend/src/database/migrations/20220411000002-add-column-schedules-and-outOfHoursMessage-to-Queues.ts @@ -0,0 +1,23 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.addColumn("Queues", "schedules", { + type: DataTypes.JSONB, + defaultValue: [] + }), + queryInterface.addColumn("Queues", "outOfHoursMessage", { + type: DataTypes.TEXT, + allowNull: true + }) + ]); + }, + + down: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.removeColumn("Queues", "schedules"), + queryInterface.removeColumn("Queues", "outOfHoursMessage") + ]); + } +}; diff --git a/backend/src/database/migrations/20220411000003-create-table-Announcements.ts b/backend/src/database/migrations/20220411000003-create-table-Announcements.ts new file mode 100644 index 0000000..9123242 --- /dev/null +++ b/backend/src/database/migrations/20220411000003-create-table-Announcements.ts @@ -0,0 +1,57 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Announcements", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + priority: { + type: DataTypes.INTEGER, + allowNull: true + }, + title: { + type: DataTypes.STRING, + allowNull: false + }, + text: { + type: DataTypes.TEXT, + allowNull: false + }, + mediaPath: { + type: DataTypes.TEXT, + allowNull: true + }, + mediaName: { + type: DataTypes.TEXT, + allowNull: true + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + status: { + type: DataTypes.BOOLEAN, + allowNull: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Announcements"); + } +}; diff --git a/backend/src/database/migrations/20220425000000-create-table-Chats.ts b/backend/src/database/migrations/20220425000000-create-table-Chats.ts new file mode 100644 index 0000000..5659c5e --- /dev/null +++ b/backend/src/database/migrations/20220425000000-create-table-Chats.ts @@ -0,0 +1,54 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Chats", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + title: { + type: DataTypes.TEXT, + defaultValue: "", + allowNull: true + }, + uuid: { + type: DataTypes.STRING, + defaultValue: "", + allowNull: true + }, + ownerId: { + type: DataTypes.INTEGER, + references: { model: "Users", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + lastMessage: { + type: DataTypes.TEXT, + allowNull: true + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Chats"); + } +}; diff --git a/backend/src/database/migrations/20220425000001-create-table-ChatUsers.ts b/backend/src/database/migrations/20220425000001-create-table-ChatUsers.ts new file mode 100644 index 0000000..67adc5a --- /dev/null +++ b/backend/src/database/migrations/20220425000001-create-table-ChatUsers.ts @@ -0,0 +1,44 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("ChatUsers", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + chatId: { + type: DataTypes.INTEGER, + references: { model: "Chats", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + userId: { + type: DataTypes.INTEGER, + references: { model: "Users", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + unreads: { + type: DataTypes.INTEGER, + defaultValue: 0 + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("ChatUsers"); + } +}; diff --git a/backend/src/database/migrations/20220425000002-create-table-ChatMessages.ts b/backend/src/database/migrations/20220425000002-create-table-ChatMessages.ts new file mode 100644 index 0000000..1dfbbd3 --- /dev/null +++ b/backend/src/database/migrations/20220425000002-create-table-ChatMessages.ts @@ -0,0 +1,53 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("ChatMessages", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + chatId: { + type: DataTypes.INTEGER, + references: { model: "Chats", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + senderId: { + type: DataTypes.INTEGER, + references: { model: "Users", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + message: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: "" + }, + mediaPath: { + type: DataTypes.TEXT, + allowNull: true + }, + mediaName: { + type: DataTypes.TEXT, + allowNull: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("ChatMessages"); + } +}; diff --git a/backend/src/database/migrations/20220512000001-create-Indexes.ts b/backend/src/database/migrations/20220512000001-create-Indexes.ts new file mode 100644 index 0000000..ae67b3b --- /dev/null +++ b/backend/src/database/migrations/20220512000001-create-Indexes.ts @@ -0,0 +1,37 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.addIndex("Schedules", ["companyId"], { + name: "idx_sched_company_id" + }), + queryInterface.addIndex("Contacts", ["companyId"], { + name: "idx_cont_company_id" + }), + queryInterface.addIndex("Tags", ["companyId"], { + name: "idx_tg_company_id" + }), + queryInterface.addIndex("Messages", ["companyId", "ticketId"], { + name: "idx_ms_company_id_ticket_id" + }), + queryInterface.addIndex("CampaignShipping", ["campaignId"], { + name: "idx_cpsh_campaign_id" + }), + queryInterface.addIndex("ContactListItems", ["contactListId"], { + name: "idx_ctli_contact_list_id" + }) + ]); + }, + + down: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.removeIndex("Schedules", "idx_sched_company_id"), + queryInterface.removeIndex("Contacts", "idx_cont_company_id"), + queryInterface.removeIndex("Tags", "idx_tg_company_id"), + queryInterface.removeIndex("Messages", "idx_ms_company_id_ticket_id"), + queryInterface.removeIndex("CampaignShipping", "idx_cpsh_campaign_id"), + queryInterface.removeIndex("ContactListItems", "idx_ctli_contact_list_id") + ]); + } +}; diff --git a/backend/src/database/migrations/20220512000002-create-subscriptions.ts b/backend/src/database/migrations/20220512000002-create-subscriptions.ts new file mode 100644 index 0000000..2c25559 --- /dev/null +++ b/backend/src/database/migrations/20220512000002-create-subscriptions.ts @@ -0,0 +1,58 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Subscriptions", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + isActive: { + type: DataTypes.BOOLEAN, + defaultValue: false + }, + expiresAt: { + type: DataTypes.DATE, + allowNull: false + }, + userPriceCents: { + type: DataTypes.INTEGER + }, + whatsPriceCents: { + type: DataTypes.INTEGER + }, + lastInvoiceUrl: { + type: DataTypes.STRING, + allowNull: true + }, + lastPlanChange: { + type: DataTypes.DATE, + allowNull: true + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE" + }, + providerSubscriptionId: { + type: DataTypes.STRING, + allowNull: false + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Subscriptions"); + } +}; diff --git a/backend/src/database/migrations/20220512000003-create-invoices.ts b/backend/src/database/migrations/20220512000003-create-invoices.ts new file mode 100644 index 0000000..108e24f --- /dev/null +++ b/backend/src/database/migrations/20220512000003-create-invoices.ts @@ -0,0 +1,44 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Invoices", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + detail: { + type: DataTypes.STRING, + }, + status: { + type: DataTypes.STRING, + }, + value: { + type: DataTypes.FLOAT + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + }, + dueDate: { + type: DataTypes.STRING, + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE" + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Invoices"); + } +}; diff --git a/backend/src/database/migrations/20220723000001-add-mediaPath-to-quickmessages.ts b/backend/src/database/migrations/20220723000001-add-mediaPath-to-quickmessages.ts new file mode 100644 index 0000000..89dba5f --- /dev/null +++ b/backend/src/database/migrations/20220723000001-add-mediaPath-to-quickmessages.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("QuickMessages", "mediaPath", { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("QuickMessages", "mediaPath"); + } +}; diff --git a/backend/src/database/migrations/20220723000002-add-mediaName-to-quickemessages.ts b/backend/src/database/migrations/20220723000002-add-mediaName-to-quickemessages.ts new file mode 100644 index 0000000..968d98a --- /dev/null +++ b/backend/src/database/migrations/20220723000002-add-mediaName-to-quickemessages.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("QuickMessages", "mediaName", { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("QuickMessages", "mediaName"); + } +}; diff --git a/backend/src/database/migrations/20221229000000-add-column-number-to-Whatsapps.ts b/backend/src/database/migrations/20221229000000-add-column-number-to-Whatsapps.ts new file mode 100644 index 0000000..5f8bf6e --- /dev/null +++ b/backend/src/database/migrations/20221229000000-add-column-number-to-Whatsapps.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "number", { + type: DataTypes.TEXT, + allowNull: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "number"); + } +}; diff --git a/backend/src/database/migrations/20222016014720-create-baileys-chats.ts b/backend/src/database/migrations/20222016014720-create-baileys-chats.ts new file mode 100644 index 0000000..e11e660 --- /dev/null +++ b/backend/src/database/migrations/20222016014720-create-baileys-chats.ts @@ -0,0 +1,44 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("BaileysChats", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + whatsappId: { + type: DataTypes.INTEGER, + references: { model: "Whatsapps", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE" + }, + jid: { + type: DataTypes.STRING, + allowNull: false + }, + conversationTimestamp: { + type: DataTypes.STRING, + allowNull: false + }, + unreadCount: { + type: DataTypes.INTEGER, + defaultValue: 0 + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("BaileysChats"); + } +}; diff --git a/backend/src/database/migrations/20222016014721-create-baileys-chats Messages.ts b/backend/src/database/migrations/20222016014721-create-baileys-chats Messages.ts new file mode 100644 index 0000000..993f52b --- /dev/null +++ b/backend/src/database/migrations/20222016014721-create-baileys-chats Messages.ts @@ -0,0 +1,42 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("BaileysMessages", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + whatsappId: { + type: DataTypes.INTEGER, + references: { model: "Whatsapps", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE" + }, + baileysChatId: { + type: DataTypes.INTEGER, + references: { model: "BaileysChats", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE" + }, + jsonMessage: { + type: DataTypes.JSON, + allowNull: false + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("BaileysMessages"); + } +}; diff --git a/backend/src/database/migrations/20230106164900-add-useCampaigns-Plans.ts b/backend/src/database/migrations/20230106164900-add-useCampaigns-Plans.ts new file mode 100644 index 0000000..d88e967 --- /dev/null +++ b/backend/src/database/migrations/20230106164900-add-useCampaigns-Plans.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Plans", "useCampaigns", { + type: DataTypes.BOOLEAN, + defaultValue: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Plans", "useCampaigns"); + } +}; diff --git a/backend/src/database/migrations/20230106164900-add-useExternalApi-Plans.ts b/backend/src/database/migrations/20230106164900-add-useExternalApi-Plans.ts new file mode 100644 index 0000000..ebdfa22 --- /dev/null +++ b/backend/src/database/migrations/20230106164900-add-useExternalApi-Plans.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Plans", "useExternalApi", { + type: DataTypes.BOOLEAN, + defaultValue: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Plans", "useExternalApi"); + } +}; diff --git a/backend/src/database/migrations/20230106164900-add-useInternalChat-Plans.ts b/backend/src/database/migrations/20230106164900-add-useInternalChat-Plans.ts new file mode 100644 index 0000000..950ff20 --- /dev/null +++ b/backend/src/database/migrations/20230106164900-add-useInternalChat-Plans.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Plans", "useInternalChat", { + type: DataTypes.BOOLEAN, + defaultValue: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Plans", "useInternalChat"); + } +}; diff --git a/backend/src/database/migrations/20230106164900-add-useSchedules-Plans.ts b/backend/src/database/migrations/20230106164900-add-useSchedules-Plans.ts new file mode 100644 index 0000000..76a3e9e --- /dev/null +++ b/backend/src/database/migrations/20230106164900-add-useSchedules-Plans.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Plans", "useSchedules", { + type: DataTypes.BOOLEAN, + defaultValue: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Plans", "useSchedules"); + } +}; diff --git a/backend/src/database/migrations/20230127091500-add-column-active-to-Contacts.ts b/backend/src/database/migrations/20230127091500-add-column-active-to-Contacts.ts new file mode 100644 index 0000000..196b2ed --- /dev/null +++ b/backend/src/database/migrations/20230127091500-add-column-active-to-Contacts.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Contacts", "active", { + type: DataTypes.BOOLEAN, + defaultValue: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Contacts", "active"); + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20230303223001-add-amountUsedBotQueues-to-tickets.ts b/backend/src/database/migrations/20230303223001-add-amountUsedBotQueues-to-tickets.ts new file mode 100644 index 0000000..0fa8ed9 --- /dev/null +++ b/backend/src/database/migrations/20230303223001-add-amountUsedBotQueues-to-tickets.ts @@ -0,0 +1,13 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Tickets", "amountUsedBotQueues", { + type: DataTypes.INTEGER + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Tickets", "amountUsedBotQueues"); + } +}; diff --git a/backend/src/database/migrations/20230417203900-add-allTickets-user.ts b/backend/src/database/migrations/20230417203900-add-allTickets-user.ts new file mode 100644 index 0000000..6275f42 --- /dev/null +++ b/backend/src/database/migrations/20230417203900-add-allTickets-user.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Users", "allTicket", { + type: DataTypes.STRING, + allowNull: false, + defaultValue: "desabled" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Users", "allTicket"); + } +}; diff --git a/backend/src/database/migrations/20230603212335-create-QueueIntegrations.ts b/backend/src/database/migrations/20230603212335-create-QueueIntegrations.ts new file mode 100644 index 0000000..e7fac19 --- /dev/null +++ b/backend/src/database/migrations/20230603212335-create-QueueIntegrations.ts @@ -0,0 +1,48 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("QueueIntegrations", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + type: { + type: DataTypes.STRING, + allowNull: false + }, + name: { + type: DataTypes.STRING, + allowNull: false, + unique: true + }, + projectName: { + type: DataTypes.STRING, + allowNull: false, + unique: true + }, + jsonContent: { + type: DataTypes.TEXT, + allowNull: false, + }, + language: { + type: DataTypes.STRING, + allowNull: false, + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("QueueIntegrations"); + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20230603212337-add-urlN8N-QueueIntegrations.ts b/backend/src/database/migrations/20230603212337-add-urlN8N-QueueIntegrations.ts new file mode 100644 index 0000000..1348c62 --- /dev/null +++ b/backend/src/database/migrations/20230603212337-add-urlN8N-QueueIntegrations.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("QueueIntegrations", "urlN8N", { + type: DataTypes.STRING, + allowNull: false, + defaultValue: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("QueueIntegrations", "urlN8N"); + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20230623095932-add-whatsapp-to-user.ts b/backend/src/database/migrations/20230623095932-add-whatsapp-to-user.ts new file mode 100644 index 0000000..b09393b --- /dev/null +++ b/backend/src/database/migrations/20230623095932-add-whatsapp-to-user.ts @@ -0,0 +1,17 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Users", "whatsappId", { + type: DataTypes.INTEGER, + references: { model: "Whatsapps", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL", + allowNull: true + },); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Users", "whatsappId"); + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20230623133903-add-chatbotAt-ticket-tracking.ts b/backend/src/database/migrations/20230623133903-add-chatbotAt-ticket-tracking.ts new file mode 100644 index 0000000..cbedb37 --- /dev/null +++ b/backend/src/database/migrations/20230623133903-add-chatbotAt-ticket-tracking.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("TicketTraking", "chatbotAt", { + type: DataTypes.DATE, + allowNull: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("TicketTraking", "chatbotAt"); + } +}; diff --git a/backend/src/database/migrations/20230628134807-add-orderQueue-Queue.ts b/backend/src/database/migrations/20230628134807-add-orderQueue-Queue.ts new file mode 100644 index 0000000..4ab7aad --- /dev/null +++ b/backend/src/database/migrations/20230628134807-add-orderQueue-Queue.ts @@ -0,0 +1,13 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Queues", "orderQueue", { + type: DataTypes.INTEGER + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Queues", "orderQueue"); + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20230711094417-add-column-companyId-to-QueueIntegrations-table.ts b/backend/src/database/migrations/20230711094417-add-column-companyId-to-QueueIntegrations-table.ts new file mode 100644 index 0000000..94a1855 --- /dev/null +++ b/backend/src/database/migrations/20230711094417-add-column-companyId-to-QueueIntegrations-table.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("QueueIntegrations", "companyId", { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("QueueIntegrations", "companyId"); + } +}; diff --git a/backend/src/database/migrations/20230711111701-add-sendIdQueue-to-whatsapp.ts b/backend/src/database/migrations/20230711111701-add-sendIdQueue-to-whatsapp.ts new file mode 100644 index 0000000..1d3174f --- /dev/null +++ b/backend/src/database/migrations/20230711111701-add-sendIdQueue-to-whatsapp.ts @@ -0,0 +1,13 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "sendIdQueue", { + type: DataTypes.INTEGER + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "sendIdQueue"); + } +}; diff --git a/backend/src/database/migrations/20230714113901-create-Files.ts b/backend/src/database/migrations/20230714113901-create-Files.ts new file mode 100644 index 0000000..51afb6e --- /dev/null +++ b/backend/src/database/migrations/20230714113901-create-Files.ts @@ -0,0 +1,41 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Files", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + message: { + type: DataTypes.TEXT, + allowNull: false + }, + createdAt: { + type: DataTypes.DATE(6), + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE(6), + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Files"); + } +}; diff --git a/backend/src/database/migrations/20230714113902-create-fileOptions.ts b/backend/src/database/migrations/20230714113902-create-fileOptions.ts new file mode 100644 index 0000000..84c66c1 --- /dev/null +++ b/backend/src/database/migrations/20230714113902-create-fileOptions.ts @@ -0,0 +1,41 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("FilesOptions", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + path: { + type: DataTypes.STRING, + allowNull: false + }, + fileId: { + type: DataTypes.INTEGER, + references: { model: "Files", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false + }, + createdAt: { + type: DataTypes.DATE(6), + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE(6), + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("FilesOptions"); + } +}; diff --git a/backend/src/database/migrations/20230723301001-add-kanban-to-Tags.ts b/backend/src/database/migrations/20230723301001-add-kanban-to-Tags.ts new file mode 100644 index 0000000..421c588 --- /dev/null +++ b/backend/src/database/migrations/20230723301001-add-kanban-to-Tags.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Tags", "kanban", { + type: DataTypes.INTEGER, + allowNull: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Tags", "kanban"); + } +}; diff --git a/backend/src/database/migrations/20230801081907-add-collumns-Ticket.ts b/backend/src/database/migrations/20230801081907-add-collumns-Ticket.ts new file mode 100644 index 0000000..89f56f6 --- /dev/null +++ b/backend/src/database/migrations/20230801081907-add-collumns-Ticket.ts @@ -0,0 +1,17 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Tickets", "fromMe", { + type: DataTypes.BOOLEAN, + defaultValue: false, + allowNull: false + }); + }, + + down: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.removeColumn("Tickets", "fromMe"), + ]) + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20230805555699-add-useInternal-Plans.ts b/backend/src/database/migrations/20230805555699-add-useInternal-Plans.ts new file mode 100644 index 0000000..7f2a755 --- /dev/null +++ b/backend/src/database/migrations/20230805555699-add-useInternal-Plans.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Plans", "useInternal", { + type: DataTypes.BOOLEAN, + defaultValue: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Plans", "useInternal"); + } +}; diff --git a/backend/src/database/migrations/20230813114236-change-ticket-lastMessage-column-type.ts b/backend/src/database/migrations/20230813114236-change-ticket-lastMessage-column-type.ts new file mode 100644 index 0000000..f85f44b --- /dev/null +++ b/backend/src/database/migrations/20230813114236-change-ticket-lastMessage-column-type.ts @@ -0,0 +1,17 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.changeColumn("Tickets", "lastMessage", { + defaultValue: "", + type: DataTypes.TEXT + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.changeColumn("Tickets", "lastMessage", { + defaultValue: "", + type: DataTypes.TEXT + }); + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20230824082607-add-mediaType-FilesOptions.ts b/backend/src/database/migrations/20230824082607-add-mediaType-FilesOptions.ts new file mode 100644 index 0000000..b2a385e --- /dev/null +++ b/backend/src/database/migrations/20230824082607-add-mediaType-FilesOptions.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("FilesOptions", "mediaType", { + type: DataTypes.STRING, + defaultValue: "", + allowNull: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("FilesOptions", "mediaType"); + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20230828143411-add-Integrations-to-tickets.ts b/backend/src/database/migrations/20230828143411-add-Integrations-to-tickets.ts new file mode 100644 index 0000000..41da7b7 --- /dev/null +++ b/backend/src/database/migrations/20230828143411-add-Integrations-to-tickets.ts @@ -0,0 +1,26 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Tickets", "useIntegration", { + type: DataTypes.BOOLEAN, + defaultValue: false, + allowNull: true, + + }), + queryInterface.addColumn("Tickets", "integrationId", { + references: { model: "QueueIntegrations", key: "id" }, + type: DataTypes.INTEGER, + defaultValue: null, + allowNull: true, + + }); + }, + + down: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.removeColumn("Tickets", "useIntegration"), + queryInterface.removeColumn("Tickets", "integrationId"), + ]) + } +}; diff --git a/backend/src/database/migrations/20230828144000-create-prompts.ts b/backend/src/database/migrations/20230828144000-create-prompts.ts new file mode 100644 index 0000000..aad49fb --- /dev/null +++ b/backend/src/database/migrations/20230828144000-create-prompts.ts @@ -0,0 +1,103 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +interface ExistingTables { + [key: string]: any; +} + +module.exports = { + up: async (queryInterface: QueryInterface) => { + const table = "Prompts"; + + const existingTables: ExistingTables = await queryInterface.showAllTables(); + + if (!existingTables.includes(table)) { + return queryInterface.createTable(table, { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + name: { + type: DataTypes.TEXT, + allowNull: false + }, + apiKey: { + type: DataTypes.TEXT, + allowNull: false + }, + prompt: { + type: DataTypes.TEXT, + allowNull: false + }, + maxTokens: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 100 + }, + maxMessages: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 10 + }, + temperature: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 1 + }, + promptTokens: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + completionTokens: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + totalTokens: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + voice: { + type: DataTypes.TEXT, + allowNull: true + }, + voiceKey: { + type: DataTypes.TEXT, + allowNull: true + }, + voiceRegion: { + type: DataTypes.TEXT, + allowNull: true + }, + queueId: { + type: DataTypes.INTEGER, + references: { model: "Queues", key: "id" }, + onUpdate: "NO ACTION", + onDelete: "NO ACTION", + allowNull: false + }, + companyId: { + type: DataTypes.INTEGER, + references: { model: "Companies", key: "id" }, + onUpdate: "NO ACTION", + onDelete: "NO ACTION", + allowNull: false + }, + createdAt: { + type: DataTypes.DATE(6), + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE(6), + allowNull: false + } + }); + } + }, + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Prompts"); + } +}; diff --git a/backend/src/database/migrations/20230828144100-add-column-promptid-into-whatsapps.ts b/backend/src/database/migrations/20230828144100-add-column-promptid-into-whatsapps.ts new file mode 100644 index 0000000..0fcfba1 --- /dev/null +++ b/backend/src/database/migrations/20230828144100-add-column-promptid-into-whatsapps.ts @@ -0,0 +1,26 @@ +import { QueryInterface, DataTypes } from "sequelize"; +interface ExistingColumns { + }; + +module.exports = { + up: async (queryInterface: QueryInterface) => { + const table = "Whatsapps"; + const column = "promptId"; + + const tableInfo: ExistingColumns = await queryInterface.describeTable(table); + if (tableInfo[column]) { + return Promise.resolve(); + } + + return queryInterface.addColumn(table, column, { + type: DataTypes.INTEGER, + references: { model: "Prompts", key: "id" }, + onUpdate: "RESTRICT", + onDelete: "RESTRICT" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "promptId"); + } +}; diff --git a/backend/src/database/migrations/20230831093000-add-useKanban-Plans.ts b/backend/src/database/migrations/20230831093000-add-useKanban-Plans.ts new file mode 100644 index 0000000..0dece8e --- /dev/null +++ b/backend/src/database/migrations/20230831093000-add-useKanban-Plans.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Plans", "useKanban", { + type: DataTypes.BOOLEAN, + defaultValue: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Plans", "useKanban"); + } +}; diff --git a/backend/src/database/migrations/20230918122800-add-media-to-Queues.ts b/backend/src/database/migrations/20230918122800-add-media-to-Queues.ts new file mode 100644 index 0000000..ac92348 --- /dev/null +++ b/backend/src/database/migrations/20230918122800-add-media-to-Queues.ts @@ -0,0 +1,20 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Queues", "mediaName", { + type: DataTypes.TEXT, + defaultValue: "", + allowNull: true + }), + queryInterface.addColumn("Queues", "mediaPath", { + type: DataTypes.TEXT, + defaultValue: "", + allowNull: true + }); + }, + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Queues", "mediaName"), + queryInterface.removeColumn("Queues", "mediaPath"); + } +}; diff --git a/backend/src/database/migrations/20230918142800-add-media-to-QueueOptions.ts b/backend/src/database/migrations/20230918142800-add-media-to-QueueOptions.ts new file mode 100644 index 0000000..d50071c --- /dev/null +++ b/backend/src/database/migrations/20230918142800-add-media-to-QueueOptions.ts @@ -0,0 +1,20 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("QueueOptions", "mediaName", { + type: DataTypes.TEXT, + defaultValue: "", + allowNull: true + }), + queryInterface.addColumn("QueueOptions", "mediaPath", { + type: DataTypes.TEXT, + defaultValue: "", + allowNull: true + }); + }, + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("QueueOptions", "mediaName"), + queryInterface.removeColumn("QueueOptions", "mediaPath"); + } +}; diff --git a/backend/src/database/migrations/20230922212337-add-integrationId-Queues.ts b/backend/src/database/migrations/20230922212337-add-integrationId-Queues.ts new file mode 100644 index 0000000..7f370ef --- /dev/null +++ b/backend/src/database/migrations/20230922212337-add-integrationId-Queues.ts @@ -0,0 +1,23 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Queues", "integrationId", { + type: DataTypes.INTEGER, + references: { model: "QueueIntegrations", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }), + queryInterface.addColumn("Whatsapps", "integrationId", { + type: DataTypes.INTEGER, + references: { model: "QueueIntegrations", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }) + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Queues", "integrationId"), + queryInterface.removeColumn("Whatsapps", "integrationId"); + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20230924212337-add-fileListId-Campaigns.ts b/backend/src/database/migrations/20230924212337-add-fileListId-Campaigns.ts new file mode 100644 index 0000000..ebb213b --- /dev/null +++ b/backend/src/database/migrations/20230924212337-add-fileListId-Campaigns.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Campaigns", "fileListId", { + type: DataTypes.INTEGER, + references: { model: "Files", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }) + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Campaigns", "fileListId") + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20231111185822-add_reset_password_column.ts b/backend/src/database/migrations/20231111185822-add_reset_password_column.ts new file mode 100644 index 0000000..8154356 --- /dev/null +++ b/backend/src/database/migrations/20231111185822-add_reset_password_column.ts @@ -0,0 +1 @@ +'use strict';module.exports={up:async(queryInterface,Sequelize)=>{await queryInterface.addColumn('Users','resetPassword',{type:Sequelize.STRING,allowNull:true,});},down:async(queryInterface,Sequelize)=>{await queryInterface.removeColumn('Users','resetPassword');},}; \ No newline at end of file diff --git a/backend/src/database/migrations/20231117000001-add-mediaName-to-schedules.ts b/backend/src/database/migrations/20231117000001-add-mediaName-to-schedules.ts new file mode 100644 index 0000000..c8395a2 --- /dev/null +++ b/backend/src/database/migrations/20231117000001-add-mediaName-to-schedules.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Schedules", "mediaName", { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Schedules", "mediaName"); + } +}; diff --git a/backend/src/database/migrations/20231117000001-add-mediaPath-to-schedules.ts b/backend/src/database/migrations/20231117000001-add-mediaPath-to-schedules.ts new file mode 100644 index 0000000..257b24d --- /dev/null +++ b/backend/src/database/migrations/20231117000001-add-mediaPath-to-schedules.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Schedules", "mediaPath", { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Schedules", "mediaPath"); + } +}; diff --git a/backend/src/database/migrations/20231127113000-add-columns-Plans.ts b/backend/src/database/migrations/20231127113000-add-columns-Plans.ts new file mode 100644 index 0000000..0bd3c98 --- /dev/null +++ b/backend/src/database/migrations/20231127113000-add-columns-Plans.ts @@ -0,0 +1,19 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Plans", "useOpenAi", { + type: DataTypes.BOOLEAN, + defaultValue: true + }), + queryInterface.addColumn("Plans", "useIntegrations", { + type: DataTypes.BOOLEAN, + defaultValue: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Plans", "useOpenAi"), + queryInterface.removeColumn("Plans", "useIntegrations"); + } +}; diff --git a/backend/src/database/migrations/20231128123537-add-typebot-QueueIntegrations.ts b/backend/src/database/migrations/20231128123537-add-typebot-QueueIntegrations.ts new file mode 100644 index 0000000..6cee910 --- /dev/null +++ b/backend/src/database/migrations/20231128123537-add-typebot-QueueIntegrations.ts @@ -0,0 +1,33 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("QueueIntegrations", "typebotSlug", { + type: DataTypes.STRING, + allowNull: false, + defaultValue: "" + }), + queryInterface.addColumn("QueueIntegrations", "typebotExpires", { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }), + queryInterface.addColumn("QueueIntegrations", "typebotKeywordFinish", { + type: DataTypes.STRING, + allowNull: false, + defaultValue: "" + }), + queryInterface.addColumn("QueueIntegrations", "typebotUnknownMessage", { + type: DataTypes.STRING, + allowNull: false, + defaultValue: "" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("QueueIntegrations", "typebotSlug"), + queryInterface.removeColumn("QueueIntegrations", "typebotExpires"), + queryInterface.removeColumn("QueueIntegrations", "typebotKeywordFinish"), + queryInterface.removeColumn("QueueIntegrations", "typebotUnknownMessage"); + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20231202143411-add-typebotSessionId-to-tickets.ts b/backend/src/database/migrations/20231202143411-add-typebotSessionId-to-tickets.ts new file mode 100644 index 0000000..9805d93 --- /dev/null +++ b/backend/src/database/migrations/20231202143411-add-typebotSessionId-to-tickets.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Tickets", "typebotSessionId", { + type: DataTypes.STRING, + defaultValue: null, + allowNull: true, + + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Tickets", "typebotSessionId"); + } +}; diff --git a/backend/src/database/migrations/20231207080337-add-typebotDelayMessage-QueueIntegrations.ts b/backend/src/database/migrations/20231207080337-add-typebotDelayMessage-QueueIntegrations.ts new file mode 100644 index 0000000..0985f6c --- /dev/null +++ b/backend/src/database/migrations/20231207080337-add-typebotDelayMessage-QueueIntegrations.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("QueueIntegrations", "typebotDelayMessage", { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 1000 + }) + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("QueueIntegrations", "typebotDelayMessage") + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20231207085011-add-typebotStatus-to-tickets.ts b/backend/src/database/migrations/20231207085011-add-typebotStatus-to-tickets.ts new file mode 100644 index 0000000..5679dfc --- /dev/null +++ b/backend/src/database/migrations/20231207085011-add-typebotStatus-to-tickets.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Tickets", "typebotStatus", { + type: DataTypes.BOOLEAN, + defaultValue: false, + allowNull: false, + + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Tickets", "typebotStatus"); + } +}; diff --git a/backend/src/database/migrations/20231214092337-add-promptId-Queues.ts b/backend/src/database/migrations/20231214092337-add-promptId-Queues.ts new file mode 100644 index 0000000..5fbbaf1 --- /dev/null +++ b/backend/src/database/migrations/20231214092337-add-promptId-Queues.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Queues", "promptId", { + type: DataTypes.INTEGER, + references: { model: "Prompts", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }) + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Queues", "promptId"); + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20231214143411-add-columns-to-whatsapps.ts b/backend/src/database/migrations/20231214143411-add-columns-to-whatsapps.ts new file mode 100644 index 0000000..048e490 --- /dev/null +++ b/backend/src/database/migrations/20231214143411-add-columns-to-whatsapps.ts @@ -0,0 +1,30 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "maxUseBotQueues", { + type: DataTypes.INTEGER, + defaultValue: 3, + allowNull: true + }), + queryInterface.addColumn("Whatsapps", "expiresTicket", { + type: DataTypes.INTEGER, + defaultValue: 0, + allowNull: true + }), + queryInterface.addColumn("Whatsapps", "expiresInactiveMessage", { + type: DataTypes.STRING, + defaultValue: "", + allowNull: true + }), + queryInterface.addColumn("Whatsapps", "timeUseBotQueues", { + type: DataTypes.INTEGER, + defaultValue: 0, + allowNull: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "companyId"); + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20231214143411-add-promptId-to-tickets.ts b/backend/src/database/migrations/20231214143411-add-promptId-to-tickets.ts new file mode 100644 index 0000000..e59f30e --- /dev/null +++ b/backend/src/database/migrations/20231214143411-add-promptId-to-tickets.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Tickets", "promptId", { + type: DataTypes.STRING, + defaultValue: null, + allowNull: true, + + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Tickets", "promptId"); + } +}; diff --git a/backend/src/database/migrations/20231218160937-add-columns-QueueIntegrations.ts b/backend/src/database/migrations/20231218160937-add-columns-QueueIntegrations.ts new file mode 100644 index 0000000..cfc6ec4 --- /dev/null +++ b/backend/src/database/migrations/20231218160937-add-columns-QueueIntegrations.ts @@ -0,0 +1,21 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("QueueIntegrations", "typebotKeywordRestart", { + type: DataTypes.STRING, + allowNull: true, + defaultValue: "" + }), + queryInterface.addColumn("QueueIntegrations", "typebotRestartMessage", { + type: DataTypes.STRING, + allowNull: true, + defaultValue: "" + }) + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("QueueIntegrations", "typebotKeywordRestart"), + queryInterface.removeColumn("QueueIntegrations", "typebotRestartMessage") + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20231219153800-add-isEdited-column-to-messages.ts b/backend/src/database/migrations/20231219153800-add-isEdited-column-to-messages.ts new file mode 100644 index 0000000..ad53d35 --- /dev/null +++ b/backend/src/database/migrations/20231219153800-add-isEdited-column-to-messages.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Messages", "isEdited", { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Messages", "isEdited"); + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20231220223517-add-column-whatsappId-to-Contacts.ts b/backend/src/database/migrations/20231220223517-add-column-whatsappId-to-Contacts.ts new file mode 100644 index 0000000..e2154cc --- /dev/null +++ b/backend/src/database/migrations/20231220223517-add-column-whatsappId-to-Contacts.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Contacts", "whatsappId", { + type: DataTypes.INTEGER, + references: { model: "Whatsapps", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Contacts", "whatsappId"); + } +}; diff --git a/backend/src/database/migrations/20232016014719-add-transferTime-and-queueIdTransfer.ts b/backend/src/database/migrations/20232016014719-add-transferTime-and-queueIdTransfer.ts new file mode 100644 index 0000000..0504915 --- /dev/null +++ b/backend/src/database/migrations/20232016014719-add-transferTime-and-queueIdTransfer.ts @@ -0,0 +1,27 @@ +import { QueryInterface, DataTypes } from "sequelize"; +// +module.exports = { + + up: (queryInterface: QueryInterface) => { + return Promise.all([ + + queryInterface.addColumn("Whatsapps", "transferQueueId", { + type: DataTypes.INTEGER, + allowNull: true, + }), + + queryInterface.addColumn("Whatsapps", "timeToTransfer", { + type: DataTypes.INTEGER, + allowNull: true, + }) + ]); + }, + + down: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.removeColumn("Whatsapps", "timeToTransfer"), + queryInterface.removeColumn("Whatsapps", "transferQueueId") + ]); + } + +}; diff --git a/backend/src/database/migrations/20240522165800-add-disablebot-to-contact.ts b/backend/src/database/migrations/20240522165800-add-disablebot-to-contact.ts new file mode 100644 index 0000000..851dd11 --- /dev/null +++ b/backend/src/database/migrations/20240522165800-add-disablebot-to-contact.ts @@ -0,0 +1,18 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.addColumn("Contacts", "disableBot", { + type: DataTypes.BOOLEAN, + defaultValue: false + }), + ]); + }, + + down: (queryInterface: QueryInterface) => { + Promise.all([ + queryInterface.removeColumn("Contacts", "disableBot"), + ]); + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20240620232001-remove-unique-constraint-from-queueintegrations.ts b/backend/src/database/migrations/20240620232001-remove-unique-constraint-from-queueintegrations.ts new file mode 100644 index 0000000..654b96f --- /dev/null +++ b/backend/src/database/migrations/20240620232001-remove-unique-constraint-from-queueintegrations.ts @@ -0,0 +1,24 @@ +import { QueryInterface, DataTypes } from 'sequelize'; + +module.exports = { + up: async (queryInterface: QueryInterface) => { + await queryInterface.removeConstraint("QueueIntegrations", "QueueIntegrations_name_key"); + await queryInterface.removeConstraint("QueueIntegrations", "QueueIntegrations_projectName_key"); + await queryInterface.removeIndex("QueueIntegrations", "QueueIntegrations_name_key"); + await queryInterface.removeIndex("QueueIntegrations", "QueueIntegrations_projectName_key"); + }, + + down: async (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.addConstraint("QueueIntegrations", ["name"], { + name: "QueueIntegrations_name_key", + type: 'unique' + }), + queryInterface.addConstraint("QueueIntegrations", ["projectName"], { + name: "QueueIntegrations_projectName_key", + type: 'unique' + }), + ]); + + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20240723000002-add-geral-to-quickemessages.ts b/backend/src/database/migrations/20240723000002-add-geral-to-quickemessages.ts new file mode 100644 index 0000000..1e0d8ad --- /dev/null +++ b/backend/src/database/migrations/20240723000002-add-geral-to-quickemessages.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("QuickMessages", "geral", { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("QuickMessages", "geral"); + } +}; diff --git a/backend/src/database/migrations/20240815183416-add-reactions-to-messages.ts b/backend/src/database/migrations/20240815183416-add-reactions-to-messages.ts new file mode 100644 index 0000000..e5e1423 --- /dev/null +++ b/backend/src/database/migrations/20240815183416-add-reactions-to-messages.ts @@ -0,0 +1,15 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.addColumn('Messages', 'reactions', { + type: Sequelize.JSON, + allowNull: true, + defaultValue: [] + }); + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.removeColumn('Messages', 'reactions'); + } +}; diff --git a/backend/src/database/migrations/20240911143705-add-isForwarded-to-messages.ts b/backend/src/database/migrations/20240911143705-add-isForwarded-to-messages.ts new file mode 100644 index 0000000..b2186f6 --- /dev/null +++ b/backend/src/database/migrations/20240911143705-add-isForwarded-to-messages.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Messages", "isForwarded", { + type: DataTypes.BOOLEAN, + defaultValue: false + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Messages", "isForwarded"); + } +}; diff --git a/backend/src/database/migrations/20240914200100-whatsapps-change-unique-name.ts b/backend/src/database/migrations/20240914200100-whatsapps-change-unique-name.ts new file mode 100644 index 0000000..ab614ea --- /dev/null +++ b/backend/src/database/migrations/20240914200100-whatsapps-change-unique-name.ts @@ -0,0 +1,33 @@ +import { QueryInterface } from "sequelize"; + +export default { + up: async (queryInterface: QueryInterface) => { + try { + // Remover a constraint existente, se necessário + await queryInterface.removeConstraint("Whatsapps", "Whatsapps_name_key"); + } catch (e) { + // No operation if the constraint does not exist + } + + // Adicionar uma nova constraint única usando array de campos e objeto separado + return queryInterface.addConstraint("Whatsapps", ["companyId", "name"], { + type: "unique", + name: "company_name_constraint" + }); + }, + + down: async (queryInterface: QueryInterface) => { + try { + // Adicionar a constraint única de volta + await queryInterface.addConstraint("Whatsapps", ["name"], { + type: "unique", + name: "Whatsapps_name_key" + }); + } catch (e) { + // No operation if the constraint already exists + } + + // Remover a constraint adicionada no método `up` + return queryInterface.removeConstraint("Whatsapps", "company_name_constraint"); + } +}; diff --git a/backend/src/database/migrations/20250227150200-create-hubnotificame.ts b/backend/src/database/migrations/20250227150200-create-hubnotificame.ts new file mode 100644 index 0000000..c9e56ab --- /dev/null +++ b/backend/src/database/migrations/20250227150200-create-hubnotificame.ts @@ -0,0 +1,54 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: async (queryInterface: QueryInterface) => { + return queryInterface.createTable("HubNotificaMe", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + userId: { + type: DataTypes.INTEGER, + allowNull: true, + references: { model: "Users", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE" + }, + companyId: { + type: DataTypes.INTEGER, + allowNull: false, + references: { model: "Companies", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE" + }, + nome: { + type: DataTypes.TEXT, + allowNull: false + }, + token: { + type: DataTypes.TEXT, + allowNull: false + }, + tipo: { + type: DataTypes.TEXT, + allowNull: false + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: new Date() + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: new Date() + } + }); + }, + + down: async (queryInterface: QueryInterface) => { + return queryInterface.dropTable("HubNotificaMe"); + } +}; diff --git a/backend/src/database/migrations/20250307152100-add-whatsapp-number-to-Users-table.ts b/backend/src/database/migrations/20250307152100-add-whatsapp-number-to-Users-table.ts new file mode 100644 index 0000000..e2e389c --- /dev/null +++ b/backend/src/database/migrations/20250307152100-add-whatsapp-number-to-Users-table.ts @@ -0,0 +1,15 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Users", "whatsappNumber", { + type: DataTypes.TEXT, + allowNull: true, + unique: false + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Users", "whatsappNumber"); + } +}; diff --git a/backend/src/database/seeds/20200904070005-create-default-company.ts b/backend/src/database/seeds/20200904070005-create-default-company.ts new file mode 100644 index 0000000..caea0e5 --- /dev/null +++ b/backend/src/database/seeds/20200904070005-create-default-company.ts @@ -0,0 +1,45 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.sequelize.transaction(t => { + return Promise.all([ + queryInterface.bulkInsert( + "Plans", + [ + { + name: "Plano 1", + users: 10, + connections: 10, + queues: 10, + value: 30, + createdAt: new Date(), + updatedAt: new Date() + } + ], + { transaction: t } + ), + queryInterface.bulkInsert( + "Companies", + [ + { + name: "Empresa 1", + planId: 1, + dueDate: "2093-03-14 04:00:00+01", + createdAt: new Date(), + updatedAt: new Date() + } + ], + { transaction: t } + ) + ]); + }); + }, + + down: async (queryInterface: QueryInterface) => { + return Promise.all([ + queryInterface.bulkDelete("Companies", {}), + queryInterface.bulkDelete("Plans", {}) + ]); + } +}; diff --git a/backend/src/database/seeds/20200904070006-create-default-user.ts b/backend/src/database/seeds/20200904070006-create-default-user.ts new file mode 100644 index 0000000..c670393 --- /dev/null +++ b/backend/src/database/seeds/20200904070006-create-default-user.ts @@ -0,0 +1,32 @@ +import { QueryInterface } from "sequelize"; +import { hash } from "bcryptjs"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.sequelize.transaction(async t => { + const passwordHash = await hash("123456", 8); + return Promise.all([ + queryInterface.bulkInsert( + "Users", + [ + { + name: "Admin", + email: "admin@admin.com", + profile: "admin", + passwordHash, + companyId: 1, + createdAt: new Date(), + updatedAt: new Date(), + super: true + } + ], + { transaction: t } + ) + ]); + }); + }, + + down: async (queryInterface: QueryInterface) => { + return queryInterface.bulkDelete("Users", {}); + } +}; diff --git a/backend/src/database/seeds/20200904070007-create-default-settings.ts b/backend/src/database/seeds/20200904070007-create-default-settings.ts new file mode 100644 index 0000000..742584f --- /dev/null +++ b/backend/src/database/seeds/20200904070007-create-default-settings.ts @@ -0,0 +1,123 @@ +import { QueryInterface } from "sequelize"; +import { hash } from "bcryptjs"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.sequelize.transaction(async t => { + return Promise.all([ + queryInterface.bulkInsert( + "Settings", + [ + { + key: "chatBotType", + value: "text", + companyId: 1, + createdAt: new Date(), + updatedAt: new Date() + }, + { + key: "sendGreetingAccepted", + value: "disabled", + companyId: 1, + createdAt: new Date(), + updatedAt: new Date(), + + }, + { + key: "sendMsgTransfTicket", + value: "disabled", + companyId: 1, + createdAt: new Date(), + updatedAt: new Date(), + + }, + { + key: "sendGreetingMessageOneQueues", + value: "disabled", + companyId: 1, + createdAt: new Date(), + updatedAt: new Date(), + + }, + { + key: "userRating", + value: "disabled", + companyId: 1, + createdAt: new Date(), + updatedAt: new Date() + }, + { + key: "scheduleType", + value: "queue", + companyId: 1, + createdAt: new Date(), + updatedAt: new Date() + }, + { + key: "CheckMsgIsGroup", + value: "enabled", + companyId: 1, + createdAt: new Date(), + updatedAt: new Date() + }, + { + key:"call", + value: "disabled", + companyId: 1, + createdAt: new Date(), + updatedAt: new Date() + }, + { + key: "ipixc", + value: "", + companyId: 1, + createdAt: new Date(), + updatedAt: new Date() + }, + { + key: "tokenixc", + value: "", + companyId: 1, + createdAt: new Date(), + updatedAt: new Date() + }, + { + key: "ipmkauth", + value: "", + companyId: 1, + createdAt: new Date(), + updatedAt: new Date() + }, + { + key: "clientidmkauth", + value: "", + companyId: 1, + createdAt: new Date(), + updatedAt: new Date() + }, + { + key: "clientsecretmkauth", + value: "", + companyId: 1, + createdAt: new Date(), + updatedAt: new Date() + }, + { + key: "asaas", + value: "", + companyId: 1, + createdAt: new Date(), + updatedAt: new Date() + }, + + ], + { transaction: t } + ) + ]); + }); + }, + + down: async (queryInterface: QueryInterface) => { + return queryInterface.bulkDelete("Settings", {}); + } +}; diff --git a/backend/src/database/seeds/20230130004700-create-alltickets-settings.ts b/backend/src/database/seeds/20230130004700-create-alltickets-settings.ts new file mode 100644 index 0000000..ffbbee8 --- /dev/null +++ b/backend/src/database/seeds/20230130004700-create-alltickets-settings.ts @@ -0,0 +1,22 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.bulkInsert( + "Settings", + [ + { + key: "allTicket", + value: "disabled", + createdAt: new Date(), + updatedAt: new Date() + } + ], + {} + ); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.bulkDelete("Settings", {}); + } +}; diff --git a/backend/src/errors/AppError.ts b/backend/src/errors/AppError.ts new file mode 100644 index 0000000..a8b1209 --- /dev/null +++ b/backend/src/errors/AppError.ts @@ -0,0 +1,12 @@ +class AppError { + public readonly message: string; + + public readonly statusCode: number; + + constructor(message: string, statusCode = 400) { + this.message = message; + this.statusCode = statusCode; + } +} + +export default AppError; diff --git a/backend/src/errors/toastError.js b/backend/src/errors/toastError.js new file mode 100644 index 0000000..8b1cb9b --- /dev/null +++ b/backend/src/errors/toastError.js @@ -0,0 +1,42 @@ +import { toast } from "react-toastify"; +import { i18n } from "../translate/i18n"; +import { isString } from 'lodash'; + +const toastError = err => { + const errorMsg = err?.response?.data?.message || err?.response?.data?.error; + if (errorMsg) { + if (i18n.exists(`backendErrors.${errorMsg}`)) { + toast.error(i18n.t(`backendErrors.${errorMsg}`), { + toastId: errorMsg, + autoClose: 2000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: false, + draggable: true, + progress: undefined, + theme: "light", + }); + return + } else { + toast.error(errorMsg, { + toastId: errorMsg, + autoClose: 2000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: false, + draggable: true, + progress: undefined, + theme: "light", + }); + return + } + } if (isString(err)) { + toast.error(err); + return + } else { + toast.error("An error occurred!"); + return + } +}; + +export default toastError; diff --git a/backend/src/helpers/CheckContactOpenTickets.ts b/backend/src/helpers/CheckContactOpenTickets.ts new file mode 100644 index 0000000..960aa9c --- /dev/null +++ b/backend/src/helpers/CheckContactOpenTickets.ts @@ -0,0 +1,31 @@ +import { Op } from "sequelize"; +import AppError from "../errors/AppError"; +import Ticket from "../models/Ticket"; + +const CheckContactOpenTickets = async (contactId: number, whatsappId?: string): Promise => { + let ticket + + if (!whatsappId) { + ticket = await Ticket.findOne({ + where: { + contactId, + status: { [Op.or]: ["open", "pending"] }, + + } + }); + } else { + ticket = await Ticket.findOne({ + where: { + contactId, + status: { [Op.or]: ["open", "pending"] }, + whatsappId + } + }); + } + console.log(ticket) + if (ticket) { + throw new AppError("ERR_OTHER_OPEN_TICKET"); + } +}; + +export default CheckContactOpenTickets; diff --git a/backend/src/helpers/CheckContactSomeTicket.ts b/backend/src/helpers/CheckContactSomeTicket.ts new file mode 100644 index 0000000..11a4042 --- /dev/null +++ b/backend/src/helpers/CheckContactSomeTicket.ts @@ -0,0 +1,18 @@ +import { Op } from "sequelize"; +import AppError from "../errors/AppError"; +import Ticket from "../models/Ticket"; + +const CheckContactSomeTickets = async ( + contactId: number, + companyId: number +): Promise => { + const ticket = await Ticket.findOne({ + where: { contactId, companyId } + }); + + if (ticket) { + throw new AppError("ERR_OTHER_OPEN_TICKET"); + } +}; + +export default CheckContactSomeTickets; diff --git a/backend/src/helpers/CheckSettings.ts b/backend/src/helpers/CheckSettings.ts new file mode 100644 index 0000000..d19122b --- /dev/null +++ b/backend/src/helpers/CheckSettings.ts @@ -0,0 +1,16 @@ +import Setting from "../models/Setting"; +import AppError from "../errors/AppError"; + +const CheckSettings = async (key: string): Promise => { + const setting = await Setting.findOne({ + where: { key } + }); + + if (!setting) { + throw new AppError("ERR_NO_SETTING_FOUND", 404); + } + + return setting.value; +}; + +export default CheckSettings; diff --git a/backend/src/helpers/ConvertMp3ToMp4.ts b/backend/src/helpers/ConvertMp3ToMp4.ts new file mode 100644 index 0000000..2a0081c --- /dev/null +++ b/backend/src/helpers/ConvertMp3ToMp4.ts @@ -0,0 +1,41 @@ + +/*import { path as ffmpegPath } from "@ffmpeg-installer/ffmpeg";*/ +import fs from "fs"; +import ffmpeg from "fluent-ffmpeg"; +import mime from "mime-types"; +import ffmpegPath from "ffmpeg-static"; + +// CONVERTER MP3 PARA MP4 +const convertMp3ToMp4 = (input: string, outputMP4: string): Promise => { + return new Promise((resolve, reject) => { + ffmpeg.setFfmpegPath(ffmpegPath); + + if (!fs.existsSync(input)) { + const errorMsg = `Input file does not exist: ${input}`; + console.error(errorMsg); + return reject(new Error(errorMsg)); + } + + ffmpeg(input) + .inputFormat("mp3") // Pode remover ou verificar se necessário + .output(outputMP4) + .outputFormat("mp4") + .on("start", (commandLine) => { + console.log(`FFmpeg command: ${commandLine}`); + }) + .on("error", (error: Error) => { + console.error("Error during conversion:", error); + reject(error); + }) + .on("progress", (progress) => { + console.log(`Processing... ${progress.percent}% complete`); + }) + .on("end", () => { + console.log("Transcoding succeeded !"); + resolve(); + }) + .run(); + }); +}; + +export { convertMp3ToMp4 }; \ No newline at end of file diff --git a/backend/src/helpers/CreateTokens.ts b/backend/src/helpers/CreateTokens.ts new file mode 100644 index 0000000..3f814c0 --- /dev/null +++ b/backend/src/helpers/CreateTokens.ts @@ -0,0 +1,32 @@ +import { sign } from "jsonwebtoken"; +import authConfig from "../config/auth"; +import User from "../models/User"; + +export const createAccessToken = (user: User): string => { + const { secret, expiresIn } = authConfig; + + return sign( + { + usarname: user.name, + profile: user.profile, + id: user.id, + companyId: user.companyId + }, + secret, + { + expiresIn + } + ); +}; + +export const createRefreshToken = (user: User): string => { + const { refreshSecret, refreshExpiresIn } = authConfig; + + return sign( + { id: user.id, tokenVersion: user.tokenVersion, companyId: user.companyId }, + refreshSecret, + { + expiresIn: refreshExpiresIn + } + ); +}; diff --git a/backend/src/helpers/Debounce.ts b/backend/src/helpers/Debounce.ts new file mode 100644 index 0000000..80665d9 --- /dev/null +++ b/backend/src/helpers/Debounce.ts @@ -0,0 +1,41 @@ +interface Timeout { + id: number; + timeout: NodeJS.Timeout; +} + +const timeouts: Timeout[] = []; + +const findAndClearTimeout = (ticketId: number) => { + if (timeouts.length > 0) { + const timeoutIndex = timeouts.findIndex(timeout => timeout.id === ticketId); + + if (timeoutIndex !== -1) { + clearTimeout(timeouts[timeoutIndex].timeout); + timeouts.splice(timeoutIndex, 1); + } + } +}; + +const debounce = ( + func: { (): Promise; (...args: never[]): void }, + wait: number, + ticketId: number +) => { + return function executedFunction(...args: never[]): void { + const later = () => { + findAndClearTimeout(ticketId); + func(...args); + }; + + findAndClearTimeout(ticketId); + + const newTimeout = { + id: ticketId, + timeout: setTimeout(later, wait) + }; + + timeouts.push(newTimeout); + }; +}; + +export { debounce }; diff --git a/backend/src/helpers/GetDefaultWhatsApp.ts b/backend/src/helpers/GetDefaultWhatsApp.ts new file mode 100644 index 0000000..8370575 --- /dev/null +++ b/backend/src/helpers/GetDefaultWhatsApp.ts @@ -0,0 +1,43 @@ +import AppError from "../errors/AppError"; +import Whatsapp from "../models/Whatsapp"; +import GetDefaultWhatsAppByUser from "./GetDefaultWhatsAppByUser"; + +const GetDefaultWhatsApp = async ( + companyId: number, + userId?: number +): Promise => { + let connection: Whatsapp; + + const defaultWhatsapp = await Whatsapp.findOne({ + where: { isDefault: true, companyId } + }); + + if (defaultWhatsapp?.status === 'CONNECTED') { + connection = defaultWhatsapp; + } else { + const whatsapp = await Whatsapp.findOne({ + where: { status: "CONNECTED", companyId } + }); + connection = whatsapp; + } + + if (userId) { + const whatsappByUser = await GetDefaultWhatsAppByUser(userId); + if (whatsappByUser?.status === 'CONNECTED') { + connection = whatsappByUser; + } else { + const whatsapp = await Whatsapp.findOne({ + where: { status: "CONNECTED", companyId } + }); + connection = whatsapp; + } + } + + if (!connection) { + throw new AppError(`ERR_NO_DEF_WAPP_FOUND in COMPANY ${companyId}`); + } + + return connection; +}; + +export default GetDefaultWhatsApp; \ No newline at end of file diff --git a/backend/src/helpers/GetDefaultWhatsAppByUser.ts b/backend/src/helpers/GetDefaultWhatsAppByUser.ts new file mode 100644 index 0000000..335129a --- /dev/null +++ b/backend/src/helpers/GetDefaultWhatsAppByUser.ts @@ -0,0 +1,18 @@ +import User from "../models/User"; +import Whatsapp from "../models/Whatsapp"; +import { logger } from "../utils/logger"; + +const GetDefaultWhatsAppByUser = async ( + userId: number +): Promise => { + const user = await User.findByPk(userId, {include: ["whatsapp"]}); + if( user === null || !user.whatsapp) { + return null; + } + + logger.info(`Found whatsapp linked to user '${user.name}' is '${user.whatsapp.name}'.`); + + return user.whatsapp; +}; + +export default GetDefaultWhatsAppByUser; diff --git a/backend/src/helpers/GetTicketWbot.ts b/backend/src/helpers/GetTicketWbot.ts new file mode 100644 index 0000000..846ae54 --- /dev/null +++ b/backend/src/helpers/GetTicketWbot.ts @@ -0,0 +1,26 @@ +import { WASocket } from "@whiskeysockets/baileys"; +import { getWbot } from "../libs/wbot"; +import GetDefaultWhatsApp from "./GetDefaultWhatsApp"; +import Ticket from "../models/Ticket"; +import { Store } from "../libs/store"; + +type Session = WASocket & { + id?: number; + store?: Store; +}; + +const GetTicketWbot = async (ticket: Ticket): Promise => { + if (!ticket.whatsappId) { + const defaultWhatsapp = await GetDefaultWhatsApp( + ticket.companyId, + ticket.userId + ); + + await ticket.$set("whatsapp", defaultWhatsapp); + } + + const wbot = getWbot(ticket.whatsappId); + return wbot; +}; + +export default GetTicketWbot; diff --git a/backend/src/helpers/GetWbotMessage.ts b/backend/src/helpers/GetWbotMessage.ts new file mode 100644 index 0000000..9b71f8f --- /dev/null +++ b/backend/src/helpers/GetWbotMessage.ts @@ -0,0 +1,42 @@ +import { proto } from "@whiskeysockets/baileys"; +import WALegacySocket from "@whiskeysockets/baileys" +import Ticket from "../models/Ticket"; +import GetTicketWbot from "./GetTicketWbot"; +import AppError from "../errors/AppError"; +import GetMessageService from "../services/MessageServices/GetMessagesService"; +import Message from "../models/Message"; + +export const GetWbotMessage = async ( + ticket: Ticket, + messageId: string +): Promise => { + const getSock = await GetTicketWbot(ticket); + + let limit = 20; + + const fetchWbotMessagesGradually = async (): Promise< + proto.WebMessageInfo | Message | null | undefined + > => { + const msgFound = await GetMessageService({ + id: messageId + }); + + return msgFound; + + + }; + + try { + const msgFound = await fetchWbotMessagesGradually(); + + if (!msgFound) { + throw new Error("Cannot found message within 100 last messages"); + } + + return msgFound; + } catch (err) { + throw new AppError("ERR_FETCH_WAPP_MSG"); + } +}; + +export default GetWbotMessage; diff --git a/backend/src/helpers/GetWhatsappWbot.ts b/backend/src/helpers/GetWhatsappWbot.ts new file mode 100644 index 0000000..24e63ba --- /dev/null +++ b/backend/src/helpers/GetWhatsappWbot.ts @@ -0,0 +1,9 @@ +import { getWbot } from "../libs/wbot"; +import Whatsapp from "../models/Whatsapp"; + +const GetWhatsappWbot = async (whatsapp: Whatsapp) => { + const wbot = await getWbot(whatsapp.id); + return wbot; +}; + +export default GetWhatsappWbot; diff --git a/backend/src/helpers/Mustache.ts b/backend/src/helpers/Mustache.ts new file mode 100644 index 0000000..2b0ad26 --- /dev/null +++ b/backend/src/helpers/Mustache.ts @@ -0,0 +1,57 @@ +import Mustache from "mustache"; +import Contact from "../models/Contact"; + +export const greeting = (): string => { + const greetings = ["Boa madrugada", "Bom dia", "Boa tarde", "Boa noite"]; + const h = new Date().getHours(); + // eslint-disable-next-line no-bitwise + return greetings[(h / 6) >> 0]; +}; + +export const firstName = (contact?: Contact): string => { + if (contact && contact?.name) { + const nameArr = contact?.name.split(' '); + return nameArr[0]; + } + return ''; +}; + +export default (body: string, contact: Contact): string => { + let ms = ""; + + const Hr = new Date(); + + const dd: string = `0${Hr.getDate()}`.slice(-2); + const mm: string = `0${Hr.getMonth() + 1}`.slice(-2); + const yy: string = Hr.getFullYear().toString(); + const hh: number = Hr.getHours(); + const min: string = `0${Hr.getMinutes()}`.slice(-2); + const ss: string = `0${Hr.getSeconds()}`.slice(-2); + + if (hh >= 6) { + ms = "Bom dia"; + } + if (hh > 11) { + ms = "Boa tarde"; + } + if (hh > 17) { + ms = "Boa noite"; + } + if (hh > 23 || hh < 6) { + ms = "Boa madrugada"; + } + + const protocol = yy + mm + dd + String(hh) + min + ss; + + const hora = `${hh}:${min}:${ss}`; + + const view = { + firstName: firstName(contact), + name: contact ? contact.name : "", + gretting: greeting(), + ms, + protocol, + hora + }; + return Mustache.render(body, view); +}; \ No newline at end of file diff --git a/backend/src/helpers/SendMessage.ts b/backend/src/helpers/SendMessage.ts new file mode 100644 index 0000000..84ce74e --- /dev/null +++ b/backend/src/helpers/SendMessage.ts @@ -0,0 +1,45 @@ +import Whatsapp from "../models/Whatsapp"; +import GetWhatsappWbot from "./GetWhatsappWbot"; +import fs from "fs"; + +import { getMessageOptions } from "../services/WbotServices/SendWhatsAppMedia"; + +export type MessageData = { + number: number | string; + body: string; + mediaPath?: string; + fileName?: string; +}; + +export const SendMessage = async ( + whatsapp: Whatsapp, + messageData: MessageData +): Promise => { + try { + const wbot = await GetWhatsappWbot(whatsapp); + const chatId = `${messageData.number}@s.whatsapp.net`; + + let message; + + if (messageData.mediaPath) { + const options = await getMessageOptions( + messageData.fileName, + messageData.mediaPath, + messageData.body + ); + if (options) { + const body = fs.readFileSync(messageData.mediaPath); + message = await wbot.sendMessage(chatId, { + ...options + }); + } + } else { + const body = `\u200e ${messageData.body}`; + message = await wbot.sendMessage(chatId, { text: body }); + } + + return message; + } catch (err: any) { + throw new Error(err); + } +}; diff --git a/backend/src/helpers/SendRefreshToken.ts b/backend/src/helpers/SendRefreshToken.ts new file mode 100644 index 0000000..4e4459a --- /dev/null +++ b/backend/src/helpers/SendRefreshToken.ts @@ -0,0 +1,5 @@ +import { Response } from "express"; + +export const SendRefreshToken = (res: Response, token: string): void => { + res.cookie("jrt", token, { httpOnly: true }); +}; diff --git a/backend/src/helpers/SerializeUser.ts b/backend/src/helpers/SerializeUser.ts new file mode 100644 index 0000000..7e50103 --- /dev/null +++ b/backend/src/helpers/SerializeUser.ts @@ -0,0 +1,30 @@ +import Queue from "../models/Queue"; +import Company from "../models/Company"; +import User from "../models/User"; +import Setting from "../models/Setting"; + +interface SerializedUser { + id: number; + name: string; + email: string; + profile: string; + companyId: number; + company: Company | null; + super: boolean; + queues: Queue[]; + allTicket: string, +} + +export const SerializeUser = async (user: User): Promise => { + return { + id: user.id, + name: user.name, + email: user.email, + profile: user.profile, + companyId: user.companyId, + company: user.company, + super: user.super, + queues: user.queues, + allTicket: user.allTicket, + }; +}; diff --git a/backend/src/helpers/SerializeWbotMsgId.ts b/backend/src/helpers/SerializeWbotMsgId.ts new file mode 100644 index 0000000..4b5886e --- /dev/null +++ b/backend/src/helpers/SerializeWbotMsgId.ts @@ -0,0 +1,12 @@ +import Message from "../models/Message"; +import Ticket from "../models/Ticket"; + +const SerializeWbotMsgId = (ticket: Ticket, message: Message): string => { + const serializedMsgId = `${message.fromMe}_${ticket.contact.number}@${ + ticket.isGroup ? "g" : "c" + }.us_${message.id}`; + + return serializedMsgId; +}; + +export default SerializeWbotMsgId; diff --git a/backend/src/helpers/SetTicketMessagesAsRead.ts b/backend/src/helpers/SetTicketMessagesAsRead.ts new file mode 100644 index 0000000..32c5f9a --- /dev/null +++ b/backend/src/helpers/SetTicketMessagesAsRead.ts @@ -0,0 +1,62 @@ +import { proto, WASocket } from "@whiskeysockets/baileys"; +// import cacheLayer from "../libs/cache"; +import { getIO } from "../libs/socket"; +import Message from "../models/Message"; +import Ticket from "../models/Ticket"; +import { logger } from "../utils/logger"; +import GetTicketWbot from "./GetTicketWbot"; + +const SetTicketMessagesAsRead = async (ticket: Ticket): Promise => { + await ticket.update({ unreadMessages: 0 }); + // await cacheLayer.set(`contacts:${ticket.contactId}:unreads`, "0"); + + try { + const wbot = await GetTicketWbot(ticket); + + const getJsonMessage = await Message.findAll({ + where: { + ticketId: ticket.id, + fromMe: false, + read: false + }, + order: [["createdAt", "DESC"]] + }); + + if (getJsonMessage.length > 0) { + const lastMessages: proto.IWebMessageInfo = JSON.parse( + JSON.stringify(getJsonMessage[0].dataJson) + ); + + if (lastMessages.key && lastMessages.key.fromMe === false) { + await (wbot as WASocket).chatModify( + { markRead: true, lastMessages: [lastMessages] }, + `${ticket.contact.number}@${ + ticket.isGroup ? "g.us" : "s.whatsapp.net" + }` + ); + } + } + + await Message.update( + { read: true }, + { + where: { + ticketId: ticket.id, + read: false + } + } + ); + } catch (err) { + logger.warn( + `Could not mark messages as read. Maybe whatsapp session disconnected? Err: ${err}` + ); + } + + const io = getIO(); + io.to(`company-${ticket.companyId}-mainchannel`).emit(`company-${ticket.companyId}-ticket`, { + action: "updateUnread", + ticketId: ticket.id + }); +}; + +export default SetTicketMessagesAsRead; diff --git a/backend/src/helpers/UpdateDeletedUserOpenTicketsStatus.ts b/backend/src/helpers/UpdateDeletedUserOpenTicketsStatus.ts new file mode 100644 index 0000000..1204974 --- /dev/null +++ b/backend/src/helpers/UpdateDeletedUserOpenTicketsStatus.ts @@ -0,0 +1,19 @@ +import Ticket from "../models/Ticket"; +import UpdateTicketService from "../services/TicketServices/UpdateTicketService"; + +const UpdateDeletedUserOpenTicketsStatus = async ( + tickets: Ticket[], + companyId: number +): Promise => { + tickets.forEach(async t => { + const ticketId = t.id.toString(); + + await UpdateTicketService({ + ticketData: { status: "pending" }, + ticketId, + companyId + }); + }); +}; + +export default UpdateDeletedUserOpenTicketsStatus; diff --git a/backend/src/helpers/authState.ts b/backend/src/helpers/authState.ts new file mode 100644 index 0000000..db8304b --- /dev/null +++ b/backend/src/helpers/authState.ts @@ -0,0 +1,77 @@ +import type { + AuthenticationCreds, + AuthenticationState, + SignalDataTypeMap +} from "@whiskeysockets/baileys"; +import { BufferJSON, initAuthCreds, proto } from "@whiskeysockets/baileys"; +import Whatsapp from "../models/Whatsapp"; + +const KEY_MAP: { [T in keyof SignalDataTypeMap]: string } = { + "pre-key": "preKeys", + session: "sessions", + "sender-key": "senderKeys", + "app-state-sync-key": "appStateSyncKeys", + "app-state-sync-version": "appStateVersions", + "sender-key-memory": "senderKeyMemory" +}; + +const authState = async ( + whatsapp: Whatsapp +): Promise<{ state: AuthenticationState; saveState: () => void }> => { + let creds: AuthenticationCreds; + let keys: any = {}; + + const saveState = async () => { + try { + await whatsapp.update({ + session: JSON.stringify({ creds, keys }, BufferJSON.replacer, 0) + }); + } catch (error) { + console.log(error); + } + }; + + // const getSessionDatabase = await whatsappById(whatsapp.id); + + if (whatsapp.session && whatsapp.session !== null) { + const result = JSON.parse(whatsapp.session, BufferJSON.reviver); + creds = result.creds; + keys = result.keys; + } else { + creds = initAuthCreds(); + keys = {}; + } + + return { + state: { + creds, + keys: { + get: (type, ids) => { + const key = KEY_MAP[type]; + return ids.reduce((dict: any, id) => { + let value = keys[key]?.[id]; + if (value) { + if (type === "app-state-sync-key") { + value = proto.Message.AppStateSyncKeyData.fromObject(value); + } + dict[id] = value; + } + return dict; + }, {}); + }, + set: (data: any) => { + // eslint-disable-next-line no-restricted-syntax, guard-for-in + for (const i in data) { + const key = KEY_MAP[i as keyof SignalDataTypeMap]; + keys[key] = keys[key] || {}; + Object.assign(keys[key], data[i]); + } + saveState(); + } + } + }, + saveState + }; +}; + +export default authState; diff --git a/backend/src/helpers/downloadHubFiles.ts b/backend/src/helpers/downloadHubFiles.ts new file mode 100644 index 0000000..6612a66 --- /dev/null +++ b/backend/src/helpers/downloadHubFiles.ts @@ -0,0 +1,96 @@ +import axios from "axios"; +import { extname, join, basename } from "path"; +import { writeFile } from "fs/promises"; +import * as fs from "fs"; +import mime from "mime-types"; +import sizeOf from "image-size"; + +export const downloadFiles = async (url: string, companyId: number, mediaType: string = "unknown") => { + try { + // Faz uma requisição HEAD para pegar o Content-Type real da URL + const headResponse = await axios.head(url); + const realContentType = headResponse.headers["content-type"] || "application/octet-stream"; + + // Baixa o arquivo + const { data } = await axios.get(url, { + responseType: "arraybuffer", + }); + + // Obtém o nome do arquivo da URL + const originalname = basename(new URL(url).pathname); + let extension = extname(originalname); // Extensão original (pode estar vazia) + let mimeType = realContentType; // Usa o Content-Type real como base + let filename; + + // Ajusta o mimeType e a extensão com base no Content-Type e no mediaType do webhook + if (mimeType === "video/mp4" && mediaType === "audio") { + // Instagram: arquivo é um áudio disfarçado de video/mp4 + mimeType = "audio/mpeg"; + extension = ".mp3"; + filename = `${Date.now()}${extension}`; + } else if (mimeType === "video/mp4") { + // Instagram ou outros: arquivo é um vídeo de verdade + mimeType = "video/mp4"; + extension = ".mp4"; + filename = `${Date.now()}${extension}`; + } else if (mimeType.startsWith("audio/")) { + // Outros áudios legítimos + mimeType = "audio/mpeg"; + extension = extension || ".mp3"; + filename = `${Date.now()}${extension}`; + } else if (mimeType.startsWith("video/")) { + // Outros vídeos legítimos + mimeType = "video/mp4"; + extension = extension || ".mp4"; + filename = `${Date.now()}${extension}`; + } else if (mimeType.startsWith("image/")) { + // Imagens + try { + const dimensions = sizeOf(data); + if (dimensions.type === "jpeg") { + mimeType = "image/jpeg"; + extension = ".jpg"; + } else if (dimensions.type === "png") { + mimeType = "image/png"; + extension = ".png"; + } else { + mimeType = "image/jpeg"; // Fallback para imagem + extension = ".jpg"; + } + filename = `${Date.now()}${extension}`; + } catch (error) { + console.warn("Erro ao identificar imagem:", error.message); + mimeType = "image/jpeg"; // Fallback seguro + extension = ".jpg"; + filename = `${Date.now()}${extension}`; + } + } else { + // Fallback para outros tipos + mimeType = mime.lookup(originalname) || "application/octet-stream"; + extension = extension || ".bin"; + filename = `${Date.now()}${extension}`; + } + + // Caminho da pasta public com companyId + const publicPath = join(__dirname, "..", "..", "public", `company${companyId}`); + const filePath = join(publicPath, filename); + + // Cria o diretório da empresa se não existir + await fs.promises.mkdir(publicPath, { recursive: true }); + + // Salva o arquivo + await writeFile(filePath, data); + + // Retorna os dados do arquivo + return { + mimeType, + extension, + filename, + filePath, + originalname, + }; + } catch (error) { + console.error("Erro ao processar a requisição:", error); + throw error; + } +}; \ No newline at end of file diff --git a/backend/src/helpers/setChannelHubWebhook.ts b/backend/src/helpers/setChannelHubWebhook.ts new file mode 100644 index 0000000..446ddc9 --- /dev/null +++ b/backend/src/helpers/setChannelHubWebhook.ts @@ -0,0 +1,53 @@ +import Whatsapp from "../models/Whatsapp"; +import { IChannel } from "../controllers/ChannelHubController"; +import { showHubToken } from "./showHubToken"; +const { + Client, + MessageSubscription +} = require("notificamehubsdk"); +require("dotenv").config(); + +export const setChannelWebhook = async ( + whatsapp: IChannel | any, + whatsappId: string +) => { + const notificameHubToken = await showHubToken(); + + const client = new Client(notificameHubToken); + + + /* USAR EM TESTE */ + //const url = `https://0513-201-75-90-49.ngrok-free.app/hub-webhook/${whatsapp.qrcode}`; + + /* USAR EM PRODUÇÃO */ + const url = `${process.env.BACKEND_URL}/hub-webhook/${whatsapp.qrcode}`; + + const subscription = new MessageSubscription( + { + url + }, + { + channel: whatsapp.qrcode + } + ); + + client + .createSubscription(subscription) + .then((response: any) => { + console.log("Webhook subscribed:", response); + }) + .catch((error: any) => { + console.log("Error:", error); + }); + + await Whatsapp.update( + { + status: "CONNECTED" + }, + { + where: { + id: whatsappId + } + } + ); +}; \ No newline at end of file diff --git a/backend/src/helpers/showHubToken.ts b/backend/src/helpers/showHubToken.ts new file mode 100644 index 0000000..2b50ef9 --- /dev/null +++ b/backend/src/helpers/showHubToken.ts @@ -0,0 +1,17 @@ +import Setting from "../models/Setting"; + +export const showHubToken = async (): Promise => { + const notificameHubToken = await Setting.findOne({ + where: { + key: "hubToken" + } + }); + + if (!notificameHubToken) { + throw new Error("Erro: Token do Notificame Hub não encontrado."); + } + + if(notificameHubToken) { + return notificameHubToken.value; + } +}; \ No newline at end of file diff --git a/backend/src/helpers/simpleObjectCache.ts b/backend/src/helpers/simpleObjectCache.ts new file mode 100644 index 0000000..4bdd2e0 --- /dev/null +++ b/backend/src/helpers/simpleObjectCache.ts @@ -0,0 +1,64 @@ +import { Logger } from "pino"; + +/** + * A simple object cache with a time-to-live (TTL) for each key + */ +export class SimpleObjectCache { + private ttl: number; + + private logger: Logger; + + private cache: Map; + + /** + * @param ttl Time to live in milliseconds + * @param logger + */ + constructor(ttl: number, logger: Logger = null) { + this.ttl = ttl; + this.logger = logger; + this.cache = new Map(); + } + + /** + * Set a key-value pair in the cache + * @param key + * @param value + * @returns void + * @example cache.set('foo', 'bar'); + * @example cache.set('foo', { bar: 'baz' }); + */ + set(key: string, value: any) { + // If a timer already exists for this key, clear it + if (this.cache.has(key)) { + clearTimeout(this.cache.get(key)!.timer); + this.logger?.debug(`Cache key ${key} was cleared`); + } + + // Set a new timer + const timer = setTimeout(() => { + this.cache.delete(key); + this.logger?.debug(`Cache key ${key} was expired`); + }, this.ttl); + + // Store the value and the timer in the cache + this.cache.set(key, { value, timer }); + this.logger?.debug(`Cache key ${key} was saved`); + } + + /** + * Get a value from the cache + * @param key + * @returns The value stored in the cache + * @example cache.get('foo'); + */ + get(key: string) { + const data = this.cache.get(key); + if (!data) { + return null; + } + + this.logger?.debug(`Cache key ${key} was accessed`); + return data.value; + } +} \ No newline at end of file diff --git a/backend/src/libs/cache.ts b/backend/src/libs/cache.ts new file mode 100644 index 0000000..ce38792 --- /dev/null +++ b/backend/src/libs/cache.ts @@ -0,0 +1,82 @@ +import Redis from "ioredis"; +import { REDIS_URI_CONNECTION } from "../config/redis"; +import util from "util"; +import * as crypto from "crypto"; + +const redis = new Redis(REDIS_URI_CONNECTION); + +function encryptParams(params: any) { + const str = JSON.stringify(params); + return crypto.createHash("sha256").update(str).digest("base64"); +} + +export function setFromParams( + key: string, + params: any, + value: string, + option?: string, + optionValue?: string | number +) { + const finalKey = `${key}:${encryptParams(params)}`; + if (option !== undefined && optionValue !== undefined) { + return set(finalKey, value, option, optionValue); + } + return set(finalKey, value); +} + +export function getFromParams(key: string, params: any) { + const finalKey = `${key}:${encryptParams(params)}`; + return get(finalKey); +} + +export function delFromParams(key: string, params: any) { + const finalKey = `${key}:${encryptParams(params)}`; + return del(finalKey); +} + +export function set( + key: string, + value: string, + option?: string, + optionValue?: string | number +) { + const setPromisefy = util.promisify(redis.set).bind(redis); + if (option !== undefined && optionValue !== undefined) { + return setPromisefy(key, value, option, optionValue); + } + + return setPromisefy(key, value); +} + +export function get(key: string) { + const getPromisefy = util.promisify(redis.get).bind(redis); + return getPromisefy(key); +} + +export function getKeys(pattern: string) { + const getKeysPromisefy = util.promisify(redis.keys).bind(redis); + return getKeysPromisefy(pattern); +} + +export function del(key: string) { + const delPromisefy = util.promisify(redis.del).bind(redis); + return delPromisefy(key); +} + +export async function delFromPattern(pattern: string) { + const all = await getKeys(pattern); + for (let item of all) { + del(item); + } +} + +export const cacheLayer = { + set, + setFromParams, + get, + getFromParams, + getKeys, + del, + delFromParams, + delFromPattern +}; diff --git a/backend/src/libs/counter.ts b/backend/src/libs/counter.ts new file mode 100644 index 0000000..77a7971 --- /dev/null +++ b/backend/src/libs/counter.ts @@ -0,0 +1,33 @@ +// I ❤️ Chat GPT + +export type Counter = { + name: string; + value: number; +}; + +export type CounterMap = Record; + +export class CounterManager { + private counters: CounterMap = {}; + + // Function to increment the value of a counter and return the current value + incrementCounter(name: string, amount: number = 1): number { + if (!this.counters[name]) { + this.counters[name] = { name, value: 0 }; + } + this.counters[name].value += amount; + return this.counters[name].value; + } + + // Function to decrement the value of a counter and return the current value + decrementCounter(name: string, amount: number = 1): number { + if (this.counters[name]) { + this.counters[name].value -= amount; + if (this.counters[name].value < 0) { + this.counters[name].value = 0; // Ensure the counter doesn't go below zero + } + return this.counters[name].value; + } + return 0; // Counter doesn't exist, return 0 + } +} diff --git a/backend/src/libs/socket.ts b/backend/src/libs/socket.ts new file mode 100644 index 0000000..9fb04ea --- /dev/null +++ b/backend/src/libs/socket.ts @@ -0,0 +1,177 @@ +import { Server as SocketIO } from "socket.io"; +import { Server } from "http"; +import AppError from "../errors/AppError"; +import { logger } from "../utils/logger"; +import User from "../models/User"; +import Queue from "../models/Queue"; +import Ticket from "../models/Ticket"; +import { verify } from "jsonwebtoken"; +import authConfig from "../config/auth"; +import { CounterManager } from "./counter"; + +let io: SocketIO; + +export const initIO = (httpServer: Server): SocketIO => { + io = new SocketIO(httpServer, { + cors: { + origin: process.env.FRONTEND_URL + } + }); + + io.on("connection", async socket => { + logger.info("Client Connected"); + const { token } = socket.handshake.query; + let tokenData = null; + try { + tokenData = verify(token as string, authConfig.secret); + logger.debug(tokenData, "io-onConnection: tokenData"); + } catch (error) { + logger.warn(`[libs/socket.ts] Error decoding token: ${error?.message}`); + socket.disconnect(); + return io; + } + const counters = new CounterManager(); + + let user: User = null; + let userId = tokenData.id; + + if (userId && userId !== "undefined" && userId !== "null") { + user = await User.findByPk(userId, { include: [ Queue ] }); + if (user) { + user.online = true; + await user.save(); + } else { + logger.info(`onConnect: User ${userId} not found`); + socket.disconnect(); + return io; + } + } else { + logger.info("onConnect: Missing userId"); + socket.disconnect(); + return io; + } + + socket.join(`company-${user.companyId}-mainchannel`); + socket.join(`user-${user.id}`); + + socket.on("joinChatBox", async (ticketId: string) => { + if (!ticketId || ticketId === "undefined") { + return; + } + Ticket.findByPk(ticketId).then( + (ticket) => { + if (ticket && ticket.companyId === user.companyId + && (ticket.userId === user.id || user.profile === "admin")) { + let c: number; + if ((c = counters.incrementCounter(`ticket-${ticketId}`)) === 1) { + socket.join(ticketId); + } + logger.debug(`joinChatbox[${c}]: Channel: ${ticketId} by user ${user.id}`) + } else { + logger.info(`Invalid attempt to join channel of ticket ${ticketId} by user ${user.id}`) + } + }, + (error) => { + logger.error(error, `Error fetching ticket ${ticketId}`); + } + ); + }); + + socket.on("leaveChatBox", async (ticketId: string) => { + if (!ticketId || ticketId === "undefined") { + return; + } + + let c: number; + // o último que sair apaga a luz + + if ((c = counters.decrementCounter(`ticket-${ticketId}`)) === 0) { + socket.leave(ticketId); + } + logger.debug(`leaveChatbox[${c}]: Channel: ${ticketId} by user ${user.id}`) + }); + + socket.on("joinNotification", async () => { + let c: number; + if ((c = counters.incrementCounter("notification")) === 1) { + if (user.profile === "admin") { + socket.join(`company-${user.companyId}-notification`); + } else { + user.queues.forEach((queue) => { + logger.debug(`User ${user.id} of company ${user.companyId} joined queue ${queue.id} channel.`); + socket.join(`queue-${queue.id}-notification`); + }); + if (user.allTicket === "enabled") { + socket.join("queue-null-notification"); + } + + } + } + logger.debug(`joinNotification[${c}]: User: ${user.id}`); + }); + + socket.on("leaveNotification", async () => { + let c: number; + if ((c = counters.decrementCounter("notification")) === 0) { + if (user.profile === "admin") { + socket.leave(`company-${user.companyId}-notification`); + } else { + user.queues.forEach((queue) => { + logger.debug(`User ${user.id} of company ${user.companyId} leaved queue ${queue.id} channel.`); + socket.leave(`queue-${queue.id}-notification`); + }); + if (user.allTicket === "enabled") { + socket.leave("queue-null-notification"); + } + } + } + logger.debug(`leaveNotification[${c}]: User: ${user.id}`); + }); + + socket.on("joinTickets", (status: string) => { + if (counters.incrementCounter(`status-${status}`) === 1) { + if (user.profile === "admin") { + logger.debug(`Admin ${user.id} of company ${user.companyId} joined ${status} tickets channel.`); + socket.join(`company-${user.companyId}-${status}`); + } else if (status === "pending") { + user.queues.forEach((queue) => { + logger.debug(`User ${user.id} of company ${user.companyId} joined queue ${queue.id} pending tickets channel.`); + socket.join(`queue-${queue.id}-pending`); + }); + if (user.allTicket === "enabled") { + socket.join("queue-null-pending"); + } + } else { + logger.debug(`User ${user.id} cannot subscribe to ${status}`); + } + } + }); + + socket.on("leaveTickets", (status: string) => { + if (counters.decrementCounter(`status-${status}`) === 0) { + if (user.profile === "admin") { + logger.debug(`Admin ${user.id} of company ${user.companyId} leaved ${status} tickets channel.`); + socket.leave(`company-${user.companyId}-${status}`); + } else if (status === "pending") { + user.queues.forEach((queue) => { + logger.debug(`User ${user.id} of company ${user.companyId} leaved queue ${queue.id} pending tickets channel.`); + socket.leave(`queue-${queue.id}-pending`); + }); + if (user.allTicket === "enabled") { + socket.leave("queue-null-pending"); + } + } + } + }); + + socket.emit("ready"); + }); + return io; +}; + +export const getIO = (): SocketIO => { + if (!io) { + throw new AppError("Socket IO not initialized"); + } + return io; +}; diff --git a/backend/src/libs/store.d.ts b/backend/src/libs/store.d.ts new file mode 100644 index 0000000..1599036 --- /dev/null +++ b/backend/src/libs/store.d.ts @@ -0,0 +1,116 @@ +import { + AnyWASocket, + BaileysEventEmitter, + Chat, + ConnectionState, + Contact, + GroupMetadata, + PresenceData, + proto, + WAMessageCursor, + WAMessageKey, + WALegacySocket +} from "@adiwajshing/baileys"; +import KeyedDB from "@adiwajshing/keyed-db"; + +export interface Store { + chats: KeyedDB; + contacts: { + [_: string]: Contact; + }; + messages: { + [_: string]: { + array: proto.IWebMessageInfo[]; + get: (id: string) => proto.IWebMessageInfo; + upsert: (item: proto.IWebMessageInfo, mode: "append" | "prepend") => void; + update: (item: proto.IWebMessageInfo) => boolean; + remove: (item: proto.IWebMessageInfo) => boolean; + updateAssign: ( + id: string, + update: Partial + ) => boolean; + clear: () => void; + filter: (contain: (item: proto.IWebMessageInfo) => boolean) => void; + toJSON: () => proto.IWebMessageInfo[]; + fromJSON: (newItems: proto.IWebMessageInfo[]) => void; + }; + }; + groupMetadata: { + [_: string]: GroupMetadata; + }; + state: ConnectionState; + presences: { + [id: string]: { + [participant: string]: PresenceData; + }; + }; + bind: (ev: BaileysEventEmitter) => void; + loadMessages: ( + jid: string, + count: number, + cursor: WAMessageCursor, + sock: WALegacySocket | undefined + ) => Promise; + loadMessage: ( + jid: string, + id: string, + sock: WALegacySocket | undefined + ) => Promise; + mostRecentMessage: ( + jid: string, + sock: WALegacySocket | undefined + ) => Promise; + fetchImageUrl: ( + jid: string, + sock: AnyWASocket | undefined + ) => Promise; + fetchGroupMetadata: ( + jid: string, + sock: AnyWASocket | undefined + ) => Promise; + fetchBroadcastListInfo: ( + jid: string, + sock: WALegacySocket | undefined + ) => Promise; + fetchMessageReceipts: ( + { remoteJid, id }: WAMessageKey, + sock: WALegacySocket | undefined + ) => Promise; + toJSON: () => { + chats: KeyedDB; + contacts: { + [_: string]: Contact; + }; + messages: { + [_: string]: { + array: proto.IWebMessageInfo[]; + get: (id: string) => proto.IWebMessageInfo; + upsert: ( + item: proto.IWebMessageInfo, + mode: "append" | "prepend" + ) => void; + update: (item: proto.IWebMessageInfo) => boolean; + remove: (item: proto.IWebMessageInfo) => boolean; + updateAssign: ( + id: string, + update: Partial + ) => boolean; + clear: () => void; + filter: (contain: (item: proto.IWebMessageInfo) => boolean) => void; + toJSON: () => proto.IWebMessageInfo[]; + fromJSON: (newItems: proto.IWebMessageInfo[]) => void; + }; + }; + }; + fromJSON: (json: { + chats: Chat[]; + contacts: { + [id: string]: Contact; + }; + messages: { + [id: string]: proto.IWebMessageInfo[]; + }; + }) => void; + writeToFile: (path: string) => void; + readFromFile: (path: string) => void; +} diff --git a/backend/src/libs/wbot.ts b/backend/src/libs/wbot.ts new file mode 100644 index 0000000..62ea556 --- /dev/null +++ b/backend/src/libs/wbot.ts @@ -0,0 +1,394 @@ +import * as Sentry from "@sentry/node"; +import makeWASocket, { + WASocket, + Browsers, + WAMessage, + DisconnectReason, + fetchLatestBaileysVersion, + makeCacheableSignalKeyStore, + makeInMemoryStore, + isJidBroadcast, + WAMessageKey, + jidNormalizedUser, + CacheStore +} from "@whiskeysockets/baileys"; +import { Op } from "sequelize"; +import { FindOptions } from "sequelize/types"; +import Whatsapp from "../models/Whatsapp"; +import { logger } from "../utils/logger"; +import MAIN_LOGGER from "@whiskeysockets/baileys/lib/Utils/logger"; +import authState from "../helpers/authState"; +import { Boom } from "@hapi/boom"; +import AppError from "../errors/AppError"; +import { getIO } from "./socket"; +import { Store } from "./store"; +import { StartWhatsAppSession } from "../services/WbotServices/StartWhatsAppSession"; +import DeleteBaileysService from "../services/BaileysServices/DeleteBaileysService"; +import NodeCache from 'node-cache'; +import Contact from "../models/Contact"; +import Ticket from "../models/Ticket"; +const loggerBaileys = MAIN_LOGGER.child({}); +loggerBaileys.level = "error"; + +const msgRetryCounterCache = new NodeCache({ + stdTTL: 600, + maxKeys: 1000, + checkperiod: 300, + useClones: false +}); + +const msgCache = new NodeCache({ + stdTTL: 60, + maxKeys: 1000, + checkperiod: 300, + useClones: false +}); + +type Session = WASocket & { + id?: number; + store?: Store; +}; + +export default function msg() { + return { + get: (key: WAMessageKey) => { + const { id } = key; + if (!id) return; + let data = msgCache.get(id); + if (data) { + try { + let msg = JSON.parse(data as string); + return msg?.message; + } catch (error) { + logger.error(error); + } + } + }, + save: (msg: WAMessage) => { + const { id } = msg.key; + const msgtxt = JSON.stringify(msg); + try { + msgCache.set(id as string, msgtxt); + } catch (error) { + logger.error(error); + } + } + } +} + +const sessions: Session[] = []; + +const retriesQrCodeMap = new Map(); + +export const getWbot = (whatsappId: number): Session => { + const sessionIndex = sessions.findIndex(s => s.id === whatsappId); + + if (sessionIndex === -1) { + throw new AppError("ERR_WAPP_NOT_INITIALIZED"); + } + return sessions[sessionIndex]; +}; + +export const removeWbot = async ( + whatsappId: number, + isLogout = true +): Promise => { + try { + const sessionIndex = sessions.findIndex(s => s.id === whatsappId); + if (sessionIndex !== -1) { + if (isLogout) { + sessions[sessionIndex].logout(); + sessions[sessionIndex].ws.close(); + } + + sessions.splice(sessionIndex, 1); + } + } catch (err) { + logger.error(err); + } +}; + +export const restartWbot = async ( + companyId: number, + session?: any +): Promise => { + try { + const options: FindOptions = { + where: { + companyId, + }, + attributes: ["id"], + } + + const whatsapp = await Whatsapp.findAll(options); + + whatsapp.map(async c => { + const sessionIndex = sessions.findIndex(s => s.id === c.id); + if (sessionIndex !== -1) { + sessions[sessionIndex].ws.close(); + } + + }); + + } catch (err) { + logger.error(err); + } +}; + +export const msgDB = msg(); + +export const initWASocket = async (whatsapp: Whatsapp): Promise => { + return new Promise(async (resolve, reject) => { + try { + (async () => { + const io = getIO(); + + const whatsappUpdate = await Whatsapp.findOne({ + where: { id: whatsapp.id } + }); + + if (!whatsappUpdate) return; + + const { id, name, provider } = whatsappUpdate; + + const { version, isLatest } = await fetchLatestBaileysVersion(); + const isLegacy = provider === "stable" ? true : false; + + logger.info(`using WA v${version.join(".")}, isLatest: ${isLatest}`); + logger.info(`isLegacy: ${isLegacy}`); + logger.info(`Starting session ${name}`); + let retriesQrCode = 0; + + let wsocket: Session = null; + const store = makeInMemoryStore({ + logger: loggerBaileys + }); + + const { state, saveState } = await authState(whatsapp); + + //const msgRetryCounterCache = new NodeCache(); + const userDevicesCache: CacheStore = new NodeCache(); + + wsocket = makeWASocket({ + logger: loggerBaileys, + printQRInTerminal: false, + auth: { + creds: state.creds, + keys: makeCacheableSignalKeyStore(state.keys, logger), + }, + version, + browser: Browsers.appropriate("Desktop"), + defaultQueryTimeoutMs: undefined, + msgRetryCounterCache, + markOnlineOnConnect: false, + connectTimeoutMs: 25_000, + retryRequestDelayMs: 500, + getMessage: msgDB.get, + emitOwnEvents: true, + fireInitQueries: true, + transactionOpts: { maxCommitRetries: 10, delayBetweenTriesMs: 3000 }, + shouldIgnoreJid: jid => isJidBroadcast(jid), + }); + + // wsocket = makeWASocket({ + // version, + // logger: loggerBaileys, + // printQRInTerminal: false, + // auth: state as AuthenticationState, + // generateHighQualityLinkPreview: false, + // shouldIgnoreJid: jid => isJidBroadcast(jid), + // browser: ["Chat", "Chrome", "10.15.7"], + // patchMessageBeforeSending: (message) => { + // const requiresPatch = !!( + // message.buttonsMessage || + // // || message.templateMessage + // message.listMessage + // ); + // if (requiresPatch) { + // message = { + // viewOnceMessage: { + // message: { + // messageContextInfo: { + // deviceListMetadataVersion: 2, + // deviceListMetadata: {}, + // }, + // ...message, + // }, + // }, + // }; + // } + + // return message; + // }, + // }) + + wsocket.ev.on( + "connection.update", + async ({ connection, lastDisconnect, qr }) => { + logger.info(`Socket ${name} Connection Update ${connection || ""} ${lastDisconnect || ""}`); + + const disconect = (lastDisconnect?.error as Boom)?.output?.statusCode; + + if (connection === "close") { + if (disconect === 403) { + await whatsapp.update({ status: "PENDING", session: "", number: "" }); + removeWbot(id, false); + + await DeleteBaileysService(whatsapp.id); + + io.emit(`company-${whatsapp.companyId}-whatsappSession`, { + action: "update", + session: whatsapp + }); + } + + if (disconect !== DisconnectReason.loggedOut) { + removeWbot(id, false); + setTimeout(() => StartWhatsAppSession(whatsapp, whatsapp.companyId), 2000); + } else { + await whatsapp.update({ status: "PENDING", session: "", number: "" }); + await DeleteBaileysService(whatsapp.id); + + io.emit(`company-${whatsapp.companyId}-whatsappSession`, { + action: "update", + session: whatsapp + }); + removeWbot(id, false); + setTimeout(() => StartWhatsAppSession(whatsapp, whatsapp.companyId), 2000); + } + } + + if (connection === "open") { + await whatsapp.update({ + status: "CONNECTED", + qrcode: "", + retries: 0, + number: + wsocket.type === "md" + ? jidNormalizedUser((wsocket as WASocket).user.id).split("@")[0] + : "-" + }); + + io.emit(`company-${whatsapp.companyId}-whatsappSession`, { + action: "update", + session: whatsapp + }); + + const sessionIndex = sessions.findIndex( + s => s.id === whatsapp.id + ); + if (sessionIndex === -1) { + wsocket.id = whatsapp.id; + sessions.push(wsocket); + } + + resolve(wsocket); + } + + if (qr !== undefined) { + if (retriesQrCodeMap.get(id) && retriesQrCodeMap.get(id) >= 3) { + await whatsapp.update({ + status: "DISCONNECTED", + qrcode: "" + }); + await DeleteBaileysService(whatsapp.id); + + io.emit(`company-${whatsapp.companyId}-whatsappSession`, { + action: "update", + session: whatsapp + }); + wsocket.ev.removeAllListeners("connection.update"); + wsocket.ws.close(); + wsocket = null; + retriesQrCodeMap.delete(id); + } else { + logger.info(`Session QRCode Generate ${name}`); + retriesQrCodeMap.set(id, (retriesQrCode += 1)); + + await whatsapp.update({ + qrcode: qr, + status: "qrcode", + retries: 0, + number: "" + }); + const sessionIndex = sessions.findIndex( + s => s.id === whatsapp.id + ); + + if (sessionIndex === -1) { + wsocket.id = whatsapp.id; + sessions.push(wsocket); + } + + io.emit(`company-${whatsapp.companyId}-whatsappSession`, { + action: "update", + session: whatsapp + }); + } + } + } + ); + wsocket.ev.on("creds.update", saveState); + + wsocket.ev.on( + "presence.update", + async ({ id: remoteJid, presences }) => { + try { + logger.debug( + { remoteJid, presences }, + "Received contact presence" + ); + if (!presences[remoteJid]?.lastKnownPresence) { + return; + } + const contact = await Contact.findOne({ + where: { + number: remoteJid.replace(/\D/g, ""), + companyId: whatsapp.companyId + } + }); + if (!contact) { + return; + } + const ticket = await Ticket.findOne({ + where: { + contactId: contact.id, + whatsappId: whatsapp.id, + status: { + [Op.or]: ["open", "pending"] + } + } + }); + + if (ticket) { + io.to(ticket.id.toString()) + .to(`company-${whatsapp.companyId}-${ticket.status}`) + .to(`queue-${ticket.queueId}-${ticket.status}`) + .emit(`company-${whatsapp.companyId}-presence`, { + ticketId: ticket.id, + presence: presences[remoteJid].lastKnownPresence + }); + } + } catch (error) { + logger.error( + { remoteJid, presences }, + "presence.update: error processing" + ); + if (error instanceof Error) { + logger.error(`Error: ${error.name} ${error.message}`); + } else { + logger.error(`Error was object of type: ${typeof error}`); + } + } + } + ); + + store.bind(wsocket.ev); + })(); + } catch (error) { + Sentry.captureException(error); + console.log(error); + reject(error); + } + }); +}; diff --git a/backend/src/middleware/envTokenAuth.ts b/backend/src/middleware/envTokenAuth.ts new file mode 100644 index 0000000..99e7617 --- /dev/null +++ b/backend/src/middleware/envTokenAuth.ts @@ -0,0 +1,32 @@ +import { Request, Response, NextFunction } from "express"; + +import AppError from "../errors/AppError"; + +type TokenPayload = { + token: string | undefined; +}; + +const envTokenAuth = ( + req: Request, + res: Response, + next: NextFunction +): void => { + try { + const { token: bodyToken } = req.body as TokenPayload; + const { token: queryToken } = req.query as TokenPayload; + + if (queryToken === process.env.ENV_TOKEN) { + return next(); + } + + if (bodyToken === process.env.ENV_TOKEN) { + return next(); + } + } catch (e) { + console.log(e); + } + + throw new AppError("Token inválido", 403); +}; + +export default envTokenAuth; diff --git a/backend/src/middleware/isAuth.ts b/backend/src/middleware/isAuth.ts new file mode 100644 index 0000000..1898f35 --- /dev/null +++ b/backend/src/middleware/isAuth.ts @@ -0,0 +1,40 @@ +import { verify } from "jsonwebtoken"; +import { Request, Response, NextFunction } from "express"; +import { logger } from "../utils/logger"; +import AppError from "../errors/AppError"; +import authConfig from "../config/auth"; + +interface TokenPayload { + id: string; + username: string; + profile: string; + companyId: number; + iat: number; + exp: number; +} + +const isAuth = (req: Request, res: Response, next: NextFunction): void => { + const authHeader = req.headers.authorization; + + if (!authHeader) { + throw new AppError("ERR_SESSION_EXPIRED", 401); + } + + const [, token] = authHeader.split(" "); + + try { + const decoded = verify(token, authConfig.secret); + const { id, profile, companyId } = decoded as TokenPayload; + req.user = { + id, + profile, + companyId + }; + } catch (err) { + throw new AppError("Invalid token. We'll try to assign a new one on next request", 403 ); + } + + return next(); +}; + +export default isAuth; diff --git a/backend/src/middleware/isSuper.ts b/backend/src/middleware/isSuper.ts new file mode 100644 index 0000000..f30dd17 --- /dev/null +++ b/backend/src/middleware/isSuper.ts @@ -0,0 +1,17 @@ +import { Request, Response, NextFunction } from "express"; +import AppError from "../errors/AppError"; +import User from "../models/User"; + +const isSuper = async (req: Request, res: Response, next: NextFunction): Promise => { + const { super:isSuper } = await User.findByPk(req.user.id); + if(!isSuper){ + throw new AppError( + "Acesso não permitido", + 401 + ); + } + + return next(); +} + +export default isSuper; diff --git a/backend/src/middleware/tokenAuth.ts b/backend/src/middleware/tokenAuth.ts new file mode 100644 index 0000000..ac883a6 --- /dev/null +++ b/backend/src/middleware/tokenAuth.ts @@ -0,0 +1,31 @@ +import { Request, Response, NextFunction } from "express"; + +import AppError from "../errors/AppError"; +import Whatsapp from "../models/Whatsapp"; + +type HeaderParams = { + Bearer: string; +}; + +const tokenAuth = async (req: Request, res: Response, next: NextFunction): Promise => { + try { + const token = req.headers.authorization.replace('Bearer ', ''); + const whatsapp = await Whatsapp.findOne({ where: { token } }); + if (whatsapp) { + req.params = { + whatsappId: whatsapp.id.toString() + } + } else { + throw new Error(); + } + } catch (err) { + throw new AppError( + "Acesso não permitido", + 401 + ); + } + + return next(); +}; + +export default tokenAuth; diff --git a/backend/src/models/Announcement.ts b/backend/src/models/Announcement.ts new file mode 100644 index 0000000..8262a8f --- /dev/null +++ b/backend/src/models/Announcement.ts @@ -0,0 +1,62 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + DataType, + BelongsTo, + ForeignKey +} from "sequelize-typescript"; +import Company from "./Company"; + +@Table +class Announcement extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + priority: number; //1 - alta, 2 - média, 3 - baixa + + @Column + title: string; + + @Column(DataType.TEXT) + text: string; + + + @Column + get mediaPath(): string | null { + if (this.getDataValue("mediaPath")) { + + return `${process.env.BACKEND_URL}${process.env.PROXY_PORT ?`:${process.env.PROXY_PORT}`:""}/public/announcements/${this.getDataValue("mediaPath")}`; + + } + return null; + } + + @Column + mediaName: string; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @Column + status: boolean; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @BelongsTo(() => Company) + company: Company; +} + +export default Announcement; diff --git a/backend/src/models/Baileys.ts b/backend/src/models/Baileys.ts new file mode 100644 index 0000000..b64c2d9 --- /dev/null +++ b/backend/src/models/Baileys.ts @@ -0,0 +1,40 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + Default, + ForeignKey +} from "sequelize-typescript"; +import Whatsapp from "./Whatsapp"; + +@Table +class Baileys extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Default(null) + @Column + contacts: string; + + @Default(null) + @Column + chats: string; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @ForeignKey(() => Whatsapp) + @Column + whatsappId: number; +} + +export default Baileys; diff --git a/backend/src/models/BaileysChats.ts b/backend/src/models/BaileysChats.ts new file mode 100644 index 0000000..a1d63e8 --- /dev/null +++ b/backend/src/models/BaileysChats.ts @@ -0,0 +1,45 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + Default, + ForeignKey, + DataType, + AllowNull, + AutoIncrement +} from "sequelize-typescript"; +import Company from "./Company"; +import Whatsapp from "./Whatsapp"; + +@Table +class BaileysChats extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + jid: string; + + @Column + conversationTimestamp: number; + + @Default(0) + @Column + unreadCount: number; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @ForeignKey(() => Whatsapp) + @Column(DataType.INTEGER) + whatsappId: string; +} + +export default BaileysChats; diff --git a/backend/src/models/Campaign.ts b/backend/src/models/Campaign.ts new file mode 100644 index 0000000..91b5a96 --- /dev/null +++ b/backend/src/models/Campaign.ts @@ -0,0 +1,115 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + ForeignKey, + BelongsTo, + HasMany +} from "sequelize-typescript"; +import CampaignShipping from "./CampaignShipping"; +import Company from "./Company"; +import ContactList from "./ContactList"; +import Whatsapp from "./Whatsapp"; +import Files from "./Files"; + +@Table({ tableName: "Campaigns" }) +class Campaign extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + name: string; + + @Column({ defaultValue: "" }) + message1: string; + + @Column({ defaultValue: "" }) + message2: string; + + @Column({ defaultValue: "" }) + message3: string; + + @Column({ defaultValue: "" }) + message4: string; + + @Column({ defaultValue: "" }) + message5: string; + + @Column({ defaultValue: "" }) + confirmationMessage1: string; + + @Column({ defaultValue: "" }) + confirmationMessage2: string; + + @Column({ defaultValue: "" }) + confirmationMessage3: string; + + @Column({ defaultValue: "" }) + confirmationMessage4: string; + + @Column({ defaultValue: "" }) + confirmationMessage5: string; + + @Column({ defaultValue: "INATIVA" }) + status: string; // INATIVA, PROGRAMADA, EM_ANDAMENTO, CANCELADA, FINALIZADA + + @Column + confirmation: boolean; + + @Column + mediaPath: string; + + @Column + mediaName: string; + + @Column + scheduledAt: Date; + + @Column + completedAt: Date; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; + + @ForeignKey(() => ContactList) + @Column + contactListId: number; + + @BelongsTo(() => ContactList) + contactList: ContactList; + + @ForeignKey(() => Whatsapp) + @Column + whatsappId: number; + + @BelongsTo(() => Whatsapp) + whatsapp: Whatsapp; + + @ForeignKey(() => Files) + @Column + fileListId: number; + + @BelongsTo(() => Files) + fileList: Files; + + @HasMany(() => CampaignShipping) + shipping: CampaignShipping[]; +} + +export default Campaign; diff --git a/backend/src/models/CampaignSetting.ts b/backend/src/models/CampaignSetting.ts new file mode 100644 index 0000000..ce9cc61 --- /dev/null +++ b/backend/src/models/CampaignSetting.ts @@ -0,0 +1,41 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + ForeignKey, + BelongsTo +} from "sequelize-typescript"; +import Company from "./Company"; + +@Table({ tableName: "CampaignSettings" }) +class CampaignSetting extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + key: string; + + @Column + value: string; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; +} + +export default CampaignSetting; diff --git a/backend/src/models/CampaignShipping.ts b/backend/src/models/CampaignShipping.ts new file mode 100644 index 0000000..f7849db --- /dev/null +++ b/backend/src/models/CampaignShipping.ts @@ -0,0 +1,67 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + ForeignKey, + BelongsTo +} from "sequelize-typescript"; +import Campaign from "./Campaign"; +import ContactListItem from "./ContactListItem"; + +@Table({ tableName: "CampaignShipping" }) +class CampaignShipping extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + jobId: string; + + @Column + number: string; + + @Column + message: string; + + @Column + confirmationMessage: string; + + @Column + confirmation: boolean; + + @ForeignKey(() => ContactListItem) + @Column + contactId: number; + + @ForeignKey(() => Campaign) + @Column + campaignId: number; + + @Column + confirmationRequestedAt: Date; + + @Column + confirmedAt: Date; + + @Column + deliveredAt: Date; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @BelongsTo(() => ContactListItem) + contact: ContactListItem; + + @BelongsTo(() => Campaign) + campaign: Campaign; +} + +export default CampaignShipping; diff --git a/backend/src/models/Chat.ts b/backend/src/models/Chat.ts new file mode 100644 index 0000000..a84dd4f --- /dev/null +++ b/backend/src/models/Chat.ts @@ -0,0 +1,72 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + HasMany, + BelongsTo, + ForeignKey, + BeforeCreate, + Default +} from "sequelize-typescript"; + +import { v4 as uuidv4 } from "uuid"; + +import ChatMessage from "./ChatMessage"; +import ChatUser from "./ChatUser"; +import Company from "./Company"; +import User from "./User"; + +@Table({ tableName: "Chats" }) +class Chat extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Default(uuidv4()) + @Column + uuid: string; + + @Column({ defaultValue: "" }) + title: string; + + @ForeignKey(() => User) + @Column + ownerId: number; + + @Column({ defaultValue: "" }) + lastMessage: string; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @BelongsTo(() => Company) + company: Company; + + @BelongsTo(() => User) + owner: User; + + @HasMany(() => ChatUser) + users: ChatUser[]; + + @HasMany(() => ChatMessage) + messages: ChatMessage[]; + + @BeforeCreate + static setUUID(chat: Chat) { + chat.uuid = uuidv4(); + } +} + +export default Chat; diff --git a/backend/src/models/ChatMessage.ts b/backend/src/models/ChatMessage.ts new file mode 100644 index 0000000..9cf9e33 --- /dev/null +++ b/backend/src/models/ChatMessage.ts @@ -0,0 +1,52 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + BelongsTo, + ForeignKey +} from "sequelize-typescript"; +import User from "./User"; +import Chat from "./Chat"; + +@Table({ tableName: "ChatMessages" }) +class ChatMessage extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @ForeignKey(() => Chat) + @Column + chatId: number; + + @ForeignKey(() => User) + @Column + senderId: number; + + @Column({ defaultValue: "" }) + message: string; + + @Column + mediaPath: string; + + @Column + mediaName: string; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @BelongsTo(() => Chat) + chat: Chat; + + @BelongsTo(() => User) + sender: User; +} + +export default ChatMessage; diff --git a/backend/src/models/ChatUser.ts b/backend/src/models/ChatUser.ts new file mode 100644 index 0000000..ecddcaa --- /dev/null +++ b/backend/src/models/ChatUser.ts @@ -0,0 +1,46 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + BelongsTo, + ForeignKey +} from "sequelize-typescript"; +import User from "./User"; +import Chat from "./Chat"; + +@Table({ tableName: "ChatUsers" }) +class ChatUser extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @ForeignKey(() => Chat) + @Column + chatId: number; + + @ForeignKey(() => User) + @Column + userId: number; + + @Column + unreads: number; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @BelongsTo(() => Chat) + chat: Chat; + + @BelongsTo(() => User) + user: User; +} + +export default ChatUser; diff --git a/backend/src/models/Company.ts b/backend/src/models/Company.ts new file mode 100644 index 0000000..a4e75f5 --- /dev/null +++ b/backend/src/models/Company.ts @@ -0,0 +1,133 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + ForeignKey, + BelongsTo, + DataType, + HasMany +} from "sequelize-typescript"; +import Contact from "./Contact"; +import Message from "./Message"; + +import Plan from "./Plan"; +import Queue from "./Queue"; +import Setting from "./Setting"; +import Ticket from "./Ticket"; +import TicketTraking from "./TicketTraking"; +import User from "./User"; +import UserRating from "./UserRating"; +import Whatsapp from "./Whatsapp"; + +@Table +class Company extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + name: string; + + @Column + phone: string; + + @Column + email: string; + + @Column + status: boolean; + + @Column + dueDate: string; + + @Column + recurrence: string; + + @Column({ + type: DataType.JSONB + }) + schedules: []; + + @ForeignKey(() => Plan) + @Column + planId: number; + + @BelongsTo(() => Plan) + plan: Plan; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @HasMany(() => User, { + onUpdate: "CASCADE", + onDelete: "CASCADE", + hooks: true + }) + users: User[]; + + @HasMany(() => UserRating, { + onUpdate: "CASCADE", + onDelete: "CASCADE", + hooks: true + }) + userRatings: UserRating[]; + + @HasMany(() => Queue, { + onUpdate: "CASCADE", + onDelete: "CASCADE", + hooks: true + }) + queues: Queue[]; + + @HasMany(() => Whatsapp, { + onUpdate: "CASCADE", + onDelete: "CASCADE", + hooks: true + }) + whatsapps: Whatsapp[]; + + @HasMany(() => Message, { + onUpdate: "CASCADE", + onDelete: "CASCADE", + hooks: true + }) + messages: Message[]; + + @HasMany(() => Contact, { + onUpdate: "CASCADE", + onDelete: "CASCADE", + hooks: true + }) + contacts: Contact[]; + + @HasMany(() => Setting, { + onUpdate: "CASCADE", + onDelete: "CASCADE", + hooks: true + }) + settings: Setting[]; + + @HasMany(() => Ticket, { + onUpdate: "CASCADE", + onDelete: "CASCADE", + hooks: true + }) + tickets: Ticket[]; + + @HasMany(() => TicketTraking, { + onUpdate: "CASCADE", + onDelete: "CASCADE", + hooks: true + }) + ticketTrankins: TicketTraking[]; +} + +export default Company; diff --git a/backend/src/models/Contact.ts b/backend/src/models/Contact.ts new file mode 100644 index 0000000..589387a --- /dev/null +++ b/backend/src/models/Contact.ts @@ -0,0 +1,98 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + AllowNull, + Unique, + Default, + HasMany, + ForeignKey, + BelongsTo +} from "sequelize-typescript"; +import ContactCustomField from "./ContactCustomField"; +import Ticket from "./Ticket"; +import Company from "./Company"; +import Schedule from "./Schedule"; +import Whatsapp from "./Whatsapp"; + +@Table +class Contact extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + name: string; + + @AllowNull(true) + @Unique + @Column + number: string; + + @AllowNull(false) + @Default("") + @Column + email: string; + + @Default("") + @Column + profilePicUrl: string; + + @Default(false) + @Column + isGroup: boolean; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @HasMany(() => Ticket) + tickets: Ticket[]; + + @HasMany(() => ContactCustomField) + extraInfo: ContactCustomField[]; + + @Default(true) + @Column + active: boolean; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @Default(false) + @Column + disableBot: boolean + + @BelongsTo(() => Company) + company: Company; + + @HasMany(() => Schedule, { + onUpdate: "CASCADE", + onDelete: "CASCADE", + hooks: true + }) + schedules: Schedule[]; + + @ForeignKey(() => Whatsapp) + @Column + whatsappId: number; + + @BelongsTo(() => Whatsapp) + whatsapp: Whatsapp; + + @Column + messengerId: string; + + @Column + instagramId: string; +} + +export default Contact; diff --git a/backend/src/models/ContactCustomField.ts b/backend/src/models/ContactCustomField.ts new file mode 100644 index 0000000..f4a9ebe --- /dev/null +++ b/backend/src/models/ContactCustomField.ts @@ -0,0 +1,41 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + ForeignKey, + BelongsTo +} from "sequelize-typescript"; +import Contact from "./Contact"; + +@Table +class ContactCustomField extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + name: string; + + @Column + value: string; + + @ForeignKey(() => Contact) + @Column + contactId: number; + + @BelongsTo(() => Contact) + contact: Contact; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; +} + +export default ContactCustomField; diff --git a/backend/src/models/ContactList.ts b/backend/src/models/ContactList.ts new file mode 100644 index 0000000..c1b500c --- /dev/null +++ b/backend/src/models/ContactList.ts @@ -0,0 +1,47 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + ForeignKey, + BelongsTo, + HasMany +} from "sequelize-typescript"; +import Company from "./Company"; +import ContactListItem from "./ContactListItem"; + +@Table({ tableName: "ContactLists" }) +class ContactList extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + name: string; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; + + @HasMany(() => ContactListItem, { + onUpdate: "CASCADE", + onDelete: "CASCADE", + hooks: true + }) + contacts: ContactListItem[]; +} + +export default ContactList; diff --git a/backend/src/models/ContactListItem.ts b/backend/src/models/ContactListItem.ts new file mode 100644 index 0000000..7eecc98 --- /dev/null +++ b/backend/src/models/ContactListItem.ts @@ -0,0 +1,61 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + AllowNull, + Default, + ForeignKey, + BelongsTo +} from "sequelize-typescript"; +import Company from "./Company"; +import ContactList from "./ContactList"; + +@Table({ tableName: "ContactListItems" }) +class ContactListItem extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @AllowNull(false) + @Column + name: string; + + @AllowNull(false) + @Column + number: string; + + @AllowNull(false) + @Default("") + @Column + email: string; + + @Column + isWhatsappValid: boolean; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; + + @ForeignKey(() => ContactList) + @Column + contactListId: number; + + @BelongsTo(() => ContactList) + contactList: ContactList; +} + +export default ContactListItem; diff --git a/backend/src/models/Files.ts b/backend/src/models/Files.ts new file mode 100644 index 0000000..2693b79 --- /dev/null +++ b/backend/src/models/Files.ts @@ -0,0 +1,44 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + HasMany, + ForeignKey +} from "sequelize-typescript"; +import Company from "./Company"; +import FilesOptions from "./FilesOptions"; + +@Table({ + tableName: "Files" +}) +class Files extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @Column + name: string; + + @Column + message: string; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @HasMany(() => FilesOptions) + options: FilesOptions[]; +} + +export default Files; diff --git a/backend/src/models/FilesOptions.ts b/backend/src/models/FilesOptions.ts new file mode 100644 index 0000000..d4ce956 --- /dev/null +++ b/backend/src/models/FilesOptions.ts @@ -0,0 +1,46 @@ +import { + Table, + Column, + Model, + ForeignKey, + PrimaryKey, + AutoIncrement, + CreatedAt, + UpdatedAt, + BelongsTo +} from "sequelize-typescript"; +import Files from "./Files"; + +@Table({ + tableName: "FilesOptions" +}) +class FilesOptions extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @ForeignKey(() => Files) + @Column + fileId: number; + + @Column + name: string; + + @Column + path: string; + + @Column + mediaType: string; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @BelongsTo(() => Files) + file: Files; +} + +export default FilesOptions; diff --git a/backend/src/models/Help.ts b/backend/src/models/Help.ts new file mode 100644 index 0000000..cbbf17e --- /dev/null +++ b/backend/src/models/Help.ts @@ -0,0 +1,39 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement +} from "sequelize-typescript"; + +@Table({ + tableName: "Helps" +}) +class Help extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + title: string; + + @Column + description: string; + + @Column + video: string; + + @Column + link: string; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; +} + +export default Help; diff --git a/backend/src/models/HubNotificaMe.ts b/backend/src/models/HubNotificaMe.ts new file mode 100644 index 0000000..dd937de --- /dev/null +++ b/backend/src/models/HubNotificaMe.ts @@ -0,0 +1,57 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + ForeignKey, + BelongsTo, + AutoIncrement +} from "sequelize-typescript"; + +import Company from "./Company"; +import User from "./User"; + +@Table({ + tableName: "HubNotificaMe", // 🔴 Garantindo que o Sequelize use o nome correto da tabela + timestamps: true +}) + +class HubNotificaMe extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + nome: string; // Adicionado o campo para o nome + + @Column + token: string; // Adicionado o campo para o token + + @Column + tipo: string; // Adicionado o campo para o tipo + + @ForeignKey(() => Company) + @Column + companyId: number; + + @ForeignKey(() => User) + @Column + userId: number; + + @BelongsTo(() => Company) + company: Company; + + @BelongsTo(() => User) + user: User; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; +} + +export default HubNotificaMe; \ No newline at end of file diff --git a/backend/src/models/Invoices.ts b/backend/src/models/Invoices.ts new file mode 100644 index 0000000..8a855a5 --- /dev/null +++ b/backend/src/models/Invoices.ts @@ -0,0 +1,44 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + AllowNull, + HasMany, + Unique +} from "sequelize-typescript"; + +@Table({ tableName: "Invoices" }) +class Invoices extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + detail: string; + + @Column + status: string; + + @Column + value: number; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @Column + dueDate: string; + + @Column + companyId: number; + +} + +export default Invoices; diff --git a/backend/src/models/Message.ts b/backend/src/models/Message.ts new file mode 100644 index 0000000..777bfe1 --- /dev/null +++ b/backend/src/models/Message.ts @@ -0,0 +1,121 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + DataType, + PrimaryKey, + Default, + BelongsTo, + ForeignKey +} from "sequelize-typescript"; +import Contact from "./Contact"; +import Ticket from "./Ticket"; +import Company from "./Company"; +import Queue from "./Queue"; + +@Table +class Message extends Model { + @PrimaryKey + @Column + id: string; + + @Column(DataType.STRING) + remoteJid: string; + + @Column(DataType.STRING) + participant: string; + + @Column(DataType.STRING) + dataJson: string; + + @Default(0) + @Column + ack: number; + + @Default(false) + @Column + read: boolean; + + @Default(false) + @Column + fromMe: boolean; + + @Column(DataType.TEXT) + body: string; + + @Column(DataType.JSON) + reactions: { type: string; userId: number; }[]; + + @Column(DataType.STRING) + get mediaUrl(): string | null { + if (this.getDataValue("mediaUrl")) { + // return `${process.env.BACKEND_URL}/public/${this.getDataValue("mediaUrl")}`; + + return `${process.env.BACKEND_URL}/public/company${this.companyId}/${this.getDataValue("mediaUrl")}`; + + } + return null; + } + @Column + mediaType: string; + + @Default(false) + @Column + isDeleted: boolean; + + @CreatedAt + @Column(DataType.DATE(6)) + createdAt: Date; + + @UpdatedAt + @Column(DataType.DATE(6)) + updatedAt: Date; + + @ForeignKey(() => Message) + @Column + quotedMsgId: string; + + @BelongsTo(() => Message, "quotedMsgId") + quotedMsg: Message; + + @ForeignKey(() => Ticket) + @Column + ticketId: number; + + @BelongsTo(() => Ticket) + ticket: Ticket; + + @ForeignKey(() => Contact) + @Column + contactId: number; + + @BelongsTo(() => Contact, "contactId") + contact: Contact; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; + + @ForeignKey(() => Queue) + @Column + queueId: number; + + @BelongsTo(() => Queue) + queue: Queue; + + @Default(false) + @Column + isEdited: boolean; + + @Default(false) + @Column + isForwarded: boolean; + +} + +export default Message; diff --git a/backend/src/models/Plan.ts b/backend/src/models/Plan.ts new file mode 100644 index 0000000..1d4d601 --- /dev/null +++ b/backend/src/models/Plan.ts @@ -0,0 +1,68 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + AllowNull, + Unique +} from "sequelize-typescript"; + +@Table +class Plan extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @AllowNull(false) + @Unique + @Column + name: string; + + @Column + users: number; + + @Column + connections: number; + + @Column + queues: number; + + @Column + value: number; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @Column + useSchedules: boolean; + + @Column + useCampaigns: boolean; + + @Column + useInternalChat: boolean; + + @Column + useExternalApi: boolean; + + @Column + useKanban: boolean; + + @Column + useOpenAi: boolean; + + @Column + useIntegrations: boolean; + + @Column + useInternal: boolean; +} + +export default Plan; diff --git a/backend/src/models/Prompt.ts b/backend/src/models/Prompt.ts new file mode 100644 index 0000000..88a9375 --- /dev/null +++ b/backend/src/models/Prompt.ts @@ -0,0 +1,87 @@ +import { + AllowNull, + AutoIncrement, + BelongsTo, + Column, + CreatedAt, + ForeignKey, + Model, + PrimaryKey, + Table, + UpdatedAt +} from "sequelize-typescript"; +import Queue from "./Queue"; +import Company from "./Company"; + +@Table +class Prompt extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @AllowNull(false) + @Column + name: string; + + @AllowNull(false) + @Column + prompt: string; + + @AllowNull(false) + @Column + apiKey: string; + + @Column({ defaultValue: 10 }) + maxMessages: number; + + @Column({ defaultValue: 100 }) + maxTokens: number; + + @Column({ defaultValue: 1 }) + temperature: number; + + @Column({ defaultValue: 0 }) + promptTokens: number; + + @Column({ defaultValue: 0 }) + completionTokens: number; + + @Column({ defaultValue: 0 }) + totalTokens: number; + + @AllowNull(false) + @Column + voice: string; + + @AllowNull(true) + @Column + voiceKey:string; + + @AllowNull(true) + @Column + voiceRegion:string; + + @AllowNull + @ForeignKey(() => Queue) + @Column + queueId: number; + + @BelongsTo(() => Queue) + queue: Queue; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; +} + +export default Prompt; diff --git a/backend/src/models/Queue.ts b/backend/src/models/Queue.ts new file mode 100644 index 0000000..e77056a --- /dev/null +++ b/backend/src/models/Queue.ts @@ -0,0 +1,109 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + AllowNull, + Unique, + BelongsToMany, + BelongsTo, + ForeignKey, + HasMany, + DataType, + Default +} from "sequelize-typescript"; +import User from "./User"; +import UserQueue from "./UserQueue"; +import Company from "./Company"; + +import Whatsapp from "./Whatsapp"; +import WhatsappQueue from "./WhatsappQueue"; +import QueueOption from "./QueueOption"; +import Prompt from "./Prompt"; +import QueueIntegrations from "./QueueIntegrations"; + +@Table +class Queue extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @AllowNull(false) + @Unique + @Column + name: string; + + @AllowNull(false) + @Unique + @Column + color: string; + + @Default("") + @Column + greetingMessage: string; + + @Default("") + @Column + outOfHoursMessage: string; + + @Column({ + type: DataType.JSONB + }) + schedules: []; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; + + @BelongsToMany(() => Whatsapp, () => WhatsappQueue) + whatsapps: Array; + + @BelongsToMany(() => User, () => UserQueue) + users: Array; + + @HasMany(() => QueueOption, { + onDelete: "DELETE", + onUpdate: "DELETE", + hooks: true + }) + options: QueueOption[]; + + @Column + orderQueue: number; + + + @ForeignKey(() => QueueIntegrations) + @Column + integrationId: number; + + @BelongsTo(() => QueueIntegrations) + queueIntegrations: QueueIntegrations; + + @ForeignKey(() => Prompt) + @Column + promptId: number; + + @BelongsTo(() => Prompt) + prompt: Prompt; + + @Column + mediaPath: string; + + @Column + mediaName: string; +} + +export default Queue; diff --git a/backend/src/models/QueueIntegrations.ts b/backend/src/models/QueueIntegrations.ts new file mode 100644 index 0000000..9412094 --- /dev/null +++ b/backend/src/models/QueueIntegrations.ts @@ -0,0 +1,82 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + DataType, + PrimaryKey, + HasMany, + AutoIncrement, + BelongsTo, + ForeignKey, + Default +} from "sequelize-typescript"; +import Queue from "./Queue"; +import Company from "./Company"; + +@Table +class QueueIntegrations extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column(DataType.TEXT) + type: string; + + @Column(DataType.TEXT) + name: string; + + @Column(DataType.TEXT) + projectName: string; + + @Column(DataType.TEXT) + jsonContent: string; + + @Column(DataType.TEXT) + urlN8N: string; + + @Column(DataType.TEXT) + language: string; + + @CreatedAt + @Column(DataType.DATE(6)) + createdAt: Date; + + @UpdatedAt + @Column(DataType.DATE(6)) + updatedAt: Date; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; + + @Column + typebotSlug: string; + + @Default(0) + @Column + typebotExpires: number; + + @Column + typebotKeywordFinish: string; + + @Column + typebotUnknownMessage: string; + + @Default(1000) + @Column + typebotDelayMessage: number + + @Column + typebotKeywordRestart: string; + + @Column + typebotRestartMessage: string; +} + +export default QueueIntegrations; \ No newline at end of file diff --git a/backend/src/models/QueueOption.ts b/backend/src/models/QueueOption.ts new file mode 100644 index 0000000..6ce9e7f --- /dev/null +++ b/backend/src/models/QueueOption.ts @@ -0,0 +1,60 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + ForeignKey, + BelongsTo, + AllowNull +} from "sequelize-typescript"; +import Queue from "./Queue"; + +@Table +class QueueOption extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + title: string; + + @AllowNull + @Column + message: string; + + @AllowNull + @Column + option: string; + + @ForeignKey(() => Queue) + @Column + queueId: number; + + @ForeignKey(() => QueueOption) + @Column + parentId: number; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @BelongsTo(() => Queue) + queue: Queue; + + @BelongsTo(() => QueueOption, { foreignKey: 'parentId' }) + parent: QueueOption; + + @Column + mediaPath: string; + + @Column + mediaName: string; +} + +export default QueueOption; diff --git a/backend/src/models/QuickMessage.ts b/backend/src/models/QuickMessage.ts new file mode 100644 index 0000000..3f47872 --- /dev/null +++ b/backend/src/models/QuickMessage.ts @@ -0,0 +1,66 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + ForeignKey, + BelongsTo, + AutoIncrement +} from "sequelize-typescript"; + +import Company from "./Company"; +import User from "./User"; + +@Table +class QuickMessage extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + shortcode: string; + + @Column + message: string; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @ForeignKey(() => User) + @Column + userId: number; + + @BelongsTo(() => Company) + company: Company; + + @Column + geral: boolean; + + @BelongsTo(() => User) + user: User; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @Column + get mediaPath(): string | null { + if (this.getDataValue("mediaPath") && this.getDataValue("companyId")) { + + return `${process.env.BACKEND_URL}${process.env.PROXY_PORT ?`:${process.env.PROXY_PORT}`:""}/public/company${this.getDataValue("companyId")}/quick/${this.getDataValue("mediaPath")}`; + + } + return null; + } + + @Column + mediaName: string; +} + +export default QuickMessage; diff --git a/backend/src/models/QuickMessage_OLD.ts b/backend/src/models/QuickMessage_OLD.ts new file mode 100644 index 0000000..20fc40b --- /dev/null +++ b/backend/src/models/QuickMessage_OLD.ts @@ -0,0 +1,66 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + ForeignKey, + BelongsTo, + AutoIncrement +} from "sequelize-typescript"; + +import Company from "./Company"; +import User from "./User"; + +@Table +class QuickMessage extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + shortcode: string; + + @Column + message: string; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @ForeignKey(() => User) + @Column + userId: number; + + @BelongsTo(() => Company) + company: Company; + + @Column + geral: boolean; + + @BelongsTo(() => User) + user: User; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @Column + get mediaPath(): string | null { + if (this.getDataValue("mediaPath")) { + + return `${process.env.BACKEND_URL}${process.env.PROXY_PORT ?`:${process.env.PROXY_PORT}`:""}/public/quickMessage/${this.getDataValue("mediaPath")}`; + + } + return null; + } + + @Column + mediaName: string; +} + +export default QuickMessage; diff --git a/backend/src/models/Schedule.ts b/backend/src/models/Schedule.ts new file mode 100644 index 0000000..3dca703 --- /dev/null +++ b/backend/src/models/Schedule.ts @@ -0,0 +1,78 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + DataType, + BelongsTo, + ForeignKey +} from "sequelize-typescript"; +import Company from "./Company"; +import Contact from "./Contact"; +import Ticket from "./Ticket"; +import User from "./User"; + +@Table +class Schedule extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column(DataType.TEXT) + body: string; + + @Column + sendAt: Date; + + @Column + sentAt: Date; + + @ForeignKey(() => Contact) + @Column + contactId: number; + + @ForeignKey(() => Ticket) + @Column + ticketId: number; + + @ForeignKey(() => User) + @Column + userId: number; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @Column(DataType.STRING) + status: string; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @BelongsTo(() => Contact, "contactId") + contact: Contact; + + @BelongsTo(() => Ticket) + ticket: Ticket; + + @BelongsTo(() => User) + user: User; + + @BelongsTo(() => Company) + company: Company; + + @Column + mediaPath: string; + + @Column + mediaName: string; +} + +export default Schedule; diff --git a/backend/src/models/Setting.ts b/backend/src/models/Setting.ts new file mode 100644 index 0000000..9b74978 --- /dev/null +++ b/backend/src/models/Setting.ts @@ -0,0 +1,42 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + ForeignKey, + BelongsTo, + AutoIncrement +} from "sequelize-typescript"; + +import Company from "./Company"; + +@Table +class Setting extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + key: string; + + @Column + value: string; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; +} + +export default Setting; diff --git a/backend/src/models/Subscriptions.ts b/backend/src/models/Subscriptions.ts new file mode 100644 index 0000000..e099d03 --- /dev/null +++ b/backend/src/models/Subscriptions.ts @@ -0,0 +1,56 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + AllowNull +} from "sequelize-typescript"; + +@Table +class Subscriptions extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + isActive: boolean; + + @AllowNull(true) + @Column + userPriceCents: number; + + @AllowNull(true) + @Column + whatsPriceCents: number; + + @AllowNull(true) + @Column + lastInvoiceUrl: string; + + @AllowNull(true) + @Column + lastPlanChange: Date; + + @AllowNull(true) + @Column + expiresAt: Date; + + @AllowNull(true) + @Column + providerSubscriptionId: string; + + @Column + companyId: number; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; +} + +export default Subscriptions; diff --git a/backend/src/models/Tag.ts b/backend/src/models/Tag.ts new file mode 100644 index 0000000..793f231 --- /dev/null +++ b/backend/src/models/Tag.ts @@ -0,0 +1,54 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + BelongsToMany, + ForeignKey, + BelongsTo, + HasMany +} from "sequelize-typescript"; +import Company from "./Company"; +import Ticket from "./Ticket"; +import TicketTag from "./TicketTag"; + +@Table +class Tag extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + name: string; + + @Column + color: string; + + @HasMany(() => TicketTag) + ticketTags: TicketTag[]; + + @BelongsToMany(() => Ticket, () => TicketTag) + tickets: Ticket[]; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @Column + kanban: number; +} + +export default Tag; diff --git a/backend/src/models/Ticket.ts b/backend/src/models/Ticket.ts new file mode 100644 index 0000000..2e350eb --- /dev/null +++ b/backend/src/models/Ticket.ts @@ -0,0 +1,154 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + ForeignKey, + BelongsTo, + HasMany, + AutoIncrement, + Default, + BeforeCreate, + BelongsToMany, + AllowNull +} from "sequelize-typescript"; +import { v4 as uuidv4 } from "uuid"; + +import Contact from "./Contact"; +import Message from "./Message"; +import Queue from "./Queue"; +import User from "./User"; +import Whatsapp from "./Whatsapp"; +import Company from "./Company"; +import QueueOption from "./QueueOption"; +import Tag from "./Tag"; +import TicketTag from "./TicketTag"; +import QueueIntegrations from "./QueueIntegrations"; +import Prompt from "./Prompt"; + +@Table +class Ticket extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column({ defaultValue: "pending" }) + status: string; + + @Column + unreadMessages: number; + + @Column + lastMessage: string; + + @Default(false) + @Column + isGroup: boolean; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @ForeignKey(() => User) + @Column + userId: number; + + @BelongsTo(() => User) + user: User; + + @ForeignKey(() => Contact) + @Column + contactId: number; + + @BelongsTo(() => Contact) + contact: Contact; + + @ForeignKey(() => Whatsapp) + @Column + whatsappId: number; + + @BelongsTo(() => Whatsapp) + whatsapp: Whatsapp; + + @ForeignKey(() => Queue) + @Column + queueId: number; + + @BelongsTo(() => Queue) + queue: Queue; + + @Column + chatbot: boolean; + + @ForeignKey(() => QueueOption) + @Column + queueOptionId: number; + + @BelongsTo(() => QueueOption) + queueOption: QueueOption; + + @HasMany(() => Message) + messages: Message[]; + + @HasMany(() => TicketTag) + ticketTags: TicketTag[]; + + @BelongsToMany(() => Tag, () => TicketTag) + tags: Tag[]; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; + + @Default(uuidv4()) + @Column + uuid: string; + + @BeforeCreate + static setUUID(ticket: Ticket) { + ticket.uuid = uuidv4(); + } + + @Default(false) + @Column + useIntegration: boolean; + + @ForeignKey(() => QueueIntegrations) + @Column + integrationId: number; + + @BelongsTo(() => QueueIntegrations) + queueIntegration: QueueIntegrations; + + @Column + typebotSessionId: string; + + @Default(false) + @Column + typebotStatus: boolean + + @ForeignKey(() => Prompt) + @Column + promptId: number; + + @BelongsTo(() => Prompt) + prompt: Prompt; + + @Column + fromMe: boolean; + + @AllowNull(false) + @Default(0) + @Column + amountUsedBotQueues: number; +} + +export default Ticket; diff --git a/backend/src/models/TicketNote.ts b/backend/src/models/TicketNote.ts new file mode 100644 index 0000000..621a15b --- /dev/null +++ b/backend/src/models/TicketNote.ts @@ -0,0 +1,55 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + ForeignKey, + BelongsTo, + AutoIncrement +} from "sequelize-typescript"; + +import Contact from "./Contact"; +import User from "./User"; +import Ticket from "./Ticket"; + +@Table +class TicketNote extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + note: string; + + @ForeignKey(() => User) + @Column + userId: number; + + @BelongsTo(() => User) + user: User; + + @ForeignKey(() => Contact) + @Column + contactId: number; + + @BelongsTo(() => Contact) + contact: Contact; + + @ForeignKey(() => Ticket) + @Column + ticketId: number; + + @BelongsTo(() => Ticket) + ticket: Ticket; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; +} + +export default TicketNote; diff --git a/backend/src/models/TicketTag.ts b/backend/src/models/TicketTag.ts new file mode 100644 index 0000000..55b4bb0 --- /dev/null +++ b/backend/src/models/TicketTag.ts @@ -0,0 +1,38 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + ForeignKey, + BelongsTo +} from "sequelize-typescript"; +import Tag from "./Tag"; +import Ticket from "./Ticket"; + +@Table({ + tableName: 'TicketTags' +}) +class TicketTag extends Model { + @ForeignKey(() => Ticket) + @Column + ticketId: number; + + @ForeignKey(() => Tag) + @Column + tagId: number; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @BelongsTo(() => Ticket) + ticket: Ticket; + + @BelongsTo(() => Tag) + tag: Tag; +} + +export default TicketTag; diff --git a/backend/src/models/TicketTraking.ts b/backend/src/models/TicketTraking.ts new file mode 100644 index 0000000..d523102 --- /dev/null +++ b/backend/src/models/TicketTraking.ts @@ -0,0 +1,80 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + ForeignKey, + BelongsTo, + AutoIncrement +} from "sequelize-typescript"; + +import Company from "./Company"; +import User from "./User"; +import Ticket from "./Ticket"; +import Whatsapp from "./Whatsapp"; + +@Table({ + tableName: "TicketTraking" +}) +class TicketTraking extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @ForeignKey(() => Ticket) + @Column + ticketId: number; + + @BelongsTo(() => Ticket) + ticket: Ticket; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; + + @ForeignKey(() => Whatsapp) + @Column + whatsappId: number; + + @BelongsTo(() => Whatsapp) + whatsapp: Whatsapp; + + @ForeignKey(() => User) + @Column + userId: number; + + @Column + rated: boolean; + + @BelongsTo(() => User) + user: User; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @Column + startedAt: Date; + + @Column + queuedAt: Date; + + @Column + finishedAt: Date; + + @Column + ratingAt: Date; + + @Column + chatbotAt: Date; +} + +export default TicketTraking; diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts new file mode 100644 index 0000000..e9da8b0 --- /dev/null +++ b/backend/src/models/User.ts @@ -0,0 +1,111 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + DataType, + BeforeCreate, + BeforeUpdate, + PrimaryKey, + AutoIncrement, + Default, + HasMany, + BelongsToMany, + ForeignKey, + BelongsTo +} from "sequelize-typescript"; +import { hash, compare } from "bcryptjs"; +import Ticket from "./Ticket"; +import Queue from "./Queue"; +import UserQueue from "./UserQueue"; +import Company from "./Company"; +import QuickMessage from "./QuickMessage"; +import Whatsapp from "./Whatsapp"; + +@Table +class User extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + name: string; + + @Column + whatsappNumber: string; + + @Column + email: string; + + @Column + allTicket: string; + + @Column(DataType.VIRTUAL) + password: string; + + @Column + passwordHash: string; + + @Default(0) + @Column + tokenVersion: number; + + @Default("admin") + @Column + profile: string; + + @Column + super: boolean; + + @Column + online: boolean; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; + + @HasMany(() => Ticket) + tickets: Ticket[]; + + @BelongsToMany(() => Queue, () => UserQueue) + queues: Queue[]; + + @HasMany(() => QuickMessage, { + onUpdate: "CASCADE", + onDelete: "CASCADE", + hooks: true + }) + quickMessages: QuickMessage[]; + + @ForeignKey(() => Whatsapp) + @Column + whatsappId: number; + + @BelongsTo(() => Whatsapp) + whatsapp: Whatsapp; + + @BeforeUpdate + @BeforeCreate + static hashPassword = async (instance: User): Promise => { + if (instance.password) { + instance.passwordHash = await hash(instance.password, 8); + } + }; + + public checkPassword = async (password: string): Promise => { + return compare(password, this.getDataValue("passwordHash")); + }; +} + +export default User; diff --git a/backend/src/models/UserQueue.ts b/backend/src/models/UserQueue.ts new file mode 100644 index 0000000..17528c2 --- /dev/null +++ b/backend/src/models/UserQueue.ts @@ -0,0 +1,29 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + ForeignKey +} from "sequelize-typescript"; +import Queue from "./Queue"; +import User from "./User"; + +@Table +class UserQueue extends Model { + @ForeignKey(() => User) + @Column + userId: number; + + @ForeignKey(() => Queue) + @Column + queueId: number; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; +} + +export default UserQueue; diff --git a/backend/src/models/UserRating.ts b/backend/src/models/UserRating.ts new file mode 100644 index 0000000..9f033e4 --- /dev/null +++ b/backend/src/models/UserRating.ts @@ -0,0 +1,58 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + ForeignKey, + BelongsTo, + AutoIncrement + } from "sequelize-typescript"; + + import Company from "./Company"; + import User from "./User"; + import Ticket from "./Ticket"; + + @Table({ + tableName: "UserRatings" + }) + class UserRating extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @ForeignKey(() => Ticket) + @Column + ticketId: number; + + @BelongsTo(() => Ticket) + ticket: Ticket; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; + + @ForeignKey(() => User) + @Column + userId: number; + + @BelongsTo(() => User) + user: User; + + @Column + rate: number; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + } + + export default UserRating; + \ No newline at end of file diff --git a/backend/src/models/Whatsapp.ts b/backend/src/models/Whatsapp.ts new file mode 100644 index 0000000..92aae98 --- /dev/null +++ b/backend/src/models/Whatsapp.ts @@ -0,0 +1,155 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + DataType, + PrimaryKey, + AutoIncrement, + Default, + AllowNull, + HasMany, + Unique, + BelongsToMany, + ForeignKey, + BelongsTo +} from "sequelize-typescript"; +import Queue from "./Queue"; +import Ticket from "./Ticket"; +import WhatsappQueue from "./WhatsappQueue"; +import Company from "./Company"; +import Prompt from "./Prompt"; +import QueueIntegrations from "./QueueIntegrations"; + +@Table +class Whatsapp extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @AllowNull + @Unique + @Column(DataType.TEXT) + name: string; + + @Column(DataType.TEXT) + session: string; + + @Column(DataType.TEXT) + qrcode: string; + + @Column + status: string; + + @Column + battery: string; + + @Column + plugged: boolean; + + @Column + retries: number; + + @Default("") + @Column(DataType.TEXT) + greetingMessage: string; + + @Default("") + @Column(DataType.TEXT) + farewellMessage: string; + + @Default("") + @Column(DataType.TEXT) + complationMessage: string; + + @Default("") + @Column(DataType.TEXT) + outOfHoursMessage: string; + + @Default("") + @Column(DataType.TEXT) + ratingMessage: string; + + @Column({ defaultValue: "stable" }) + provider: string; + + @Default(false) + @AllowNull + @Column + isDefault: boolean; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @HasMany(() => Ticket) + tickets: Ticket[]; + + @BelongsToMany(() => Queue, () => WhatsappQueue) + queues: Array; + + @HasMany(() => WhatsappQueue) + whatsappQueues: WhatsappQueue[]; + + @ForeignKey(() => Company) + @Column + companyId: number; + + @BelongsTo(() => Company) + company: Company; + + @Column + token: string; + + //@Default(0) + //@Column + //timeSendQueue: number; + + //@Column + //sendIdQueue: number; + + @Column + transferQueueId: number; + + @Column + timeToTransfer: number; + + + @ForeignKey(() => Prompt) + @Column + promptId: number; + + @BelongsTo(() => Prompt) + prompt: Prompt; + + @ForeignKey(() => QueueIntegrations) + @Column + integrationId: number; + + @BelongsTo(() => QueueIntegrations) + queueIntegrations: QueueIntegrations; + + @Column + maxUseBotQueues: number; + + @Column + timeUseBotQueues: string; + + @Column + expiresTicket: number; + + @Column + number: string; + + @Column + expiresInactiveMessage: string; + + @Column + type: string; +} + +export default Whatsapp; diff --git a/backend/src/models/WhatsappQueue.ts b/backend/src/models/WhatsappQueue.ts new file mode 100644 index 0000000..b68aaa0 --- /dev/null +++ b/backend/src/models/WhatsappQueue.ts @@ -0,0 +1,33 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + ForeignKey, + BelongsTo +} from "sequelize-typescript"; +import Queue from "./Queue"; +import Whatsapp from "./Whatsapp"; + +@Table +class WhatsappQueue extends Model { + @ForeignKey(() => Whatsapp) + @Column + whatsappId: number; + + @ForeignKey(() => Queue) + @Column + queueId: number; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @BelongsTo(() => Queue) + queue: Queue; +} + +export default WhatsappQueue; diff --git a/backend/src/queues.ts b/backend/src/queues.ts new file mode 100644 index 0000000..80ae160 --- /dev/null +++ b/backend/src/queues.ts @@ -0,0 +1,973 @@ +import * as Sentry from "@sentry/node"; +import BullQueue from "bull"; +import { addSeconds, differenceInSeconds } from "date-fns"; +import { isArray, isEmpty, isNil } from "lodash"; +import moment from "moment"; +import path from "path"; +import { Op, QueryTypes } from "sequelize"; +import sequelize from "./database"; +import GetDefaultWhatsApp from "./helpers/GetDefaultWhatsApp"; +import GetWhatsappWbot from "./helpers/GetWhatsappWbot"; +import formatBody from "./helpers/Mustache"; +import { MessageData, SendMessage } from "./helpers/SendMessage"; +import { getIO } from "./libs/socket"; +import { getWbot } from "./libs/wbot"; +import Campaign from "./models/Campaign"; +import CampaignSetting from "./models/CampaignSetting"; +import CampaignShipping from "./models/CampaignShipping"; +import Company from "./models/Company"; +import Contact from "./models/Contact"; +import ContactList from "./models/ContactList"; +import ContactListItem from "./models/ContactListItem"; +import Plan from "./models/Plan"; +import Schedule from "./models/Schedule"; +import User from "./models/User"; +import Whatsapp from "./models/Whatsapp"; +import ShowFileService from "./services/FileServices/ShowService"; +import { getMessageOptions } from "./services/WbotServices/SendWhatsAppMedia"; +import { ClosedAllOpenTickets } from "./services/WbotServices/wbotClosedTickets"; +import { logger } from "./utils/logger"; + + +const nodemailer = require('nodemailer'); +const CronJob = require('cron').CronJob; + +const connection = process.env.REDIS_URI || ""; +const limiterMax = process.env.REDIS_OPT_LIMITER_MAX || 1; +const limiterDuration = process.env.REDIS_OPT_LIMITER_DURATION || 3000; + +interface ProcessCampaignData { + id: number; + delay: number; +} + +interface PrepareContactData { + contactId: number; + campaignId: number; + delay: number; + variables: any[]; +} + +interface DispatchCampaignData { + campaignId: number; + campaignShippingId: number; + contactListItemId: number; +} + +export const userMonitor = new BullQueue("UserMonitor", connection); + +export const queueMonitor = new BullQueue("QueueMonitor", connection); + +export const messageQueue = new BullQueue("MessageQueue", connection, { + limiter: { + max: limiterMax as number, + duration: limiterDuration as number + } +}); + +export const scheduleMonitor = new BullQueue("ScheduleMonitor", connection); +export const sendScheduledMessages = new BullQueue( + "SendSacheduledMessages", + connection +); + +export const campaignQueue = new BullQueue("CampaignQueue", connection); + +async function handleSendMessage(job) { + try { + const { data } = job; + + const whatsapp = await Whatsapp.findByPk(data.whatsappId); + + if (whatsapp == null) { + throw Error("Whatsapp não identificado"); + } + + const messageData: MessageData = data.data; + + await SendMessage(whatsapp, messageData); + } catch (e: any) { + Sentry.captureException(e); + logger.error("MessageQueue -> SendMessage: error", e.message); + throw e; + } +} + +{/*async function handleVerifyQueue(job) { + logger.info("Buscando atendimentos perdidos nas filas"); + try { + const companies = await Company.findAll({ + attributes: ['id', 'name'], + where: { + status: true, + dueDate: { + [Op.gt]: Sequelize.literal('CURRENT_DATE') + } + }, + include: [ + { + model: Whatsapp, attributes: ["id", "name", "status", "timeSendQueue", "sendIdQueue"], where: { + timeSendQueue: { + [Op.gt]: 0 + } + } + }, + ] + }); */} + +{/* companies.map(async c => { + c.whatsapps.map(async w => { + + if (w.status === "CONNECTED") { + + var companyId = c.id; + + const moveQueue = w.timeSendQueue ? w.timeSendQueue : 0; + const moveQueueId = w.sendIdQueue; + const moveQueueTime = moveQueue; + const idQueue = moveQueueId; + const timeQueue = moveQueueTime; + + if (moveQueue > 0) { + + if (!isNaN(idQueue) && Number.isInteger(idQueue) && !isNaN(timeQueue) && Number.isInteger(timeQueue)) { + + const tempoPassado = moment().subtract(timeQueue, "minutes").utc().format(); + // const tempoAgora = moment().utc().format(); + + const { count, rows: tickets } = await Ticket.findAndCountAll({ + where: { + status: "pending", + queueId: null, + companyId: companyId, + whatsappId: w.id, + updatedAt: { + [Op.lt]: tempoPassado + } + }, + include: [ + { + model: Contact, + as: "contact", + attributes: ["id", "name", "number", "email", "profilePicUrl"], + include: ["extraInfo"] + } + ] + }); + + if (count > 0) { + tickets.map(async ticket => { + await ticket.update({ + queueId: idQueue + }); + + await ticket.reload(); + + const io = getIO(); + io.to(ticket.status) + .to("notification") + .to(ticket.id.toString()) + .emit(`company-${companyId}-ticket`, { + action: "update", + ticket, + ticketId: ticket.id + }); + + // io.to("pending").emit(`company-${companyId}-ticket`, { + // action: "update", + // ticket, + // }); + + logger.info(`Atendimento Perdido: ${ticket.id} - Empresa: ${companyId}`); + }); + } else { + logger.info(`Nenhum atendimento perdido encontrado - Empresa: ${companyId}`); + } + } else { + logger.info(`Condição não respeitada - Empresa: ${companyId}`); + } + } + } + }); + }); + } catch (e: any) { + Sentry.captureException(e); + logger.error("SearchForQueue -> VerifyQueue: error", e.message); + throw e; + } +}; */} + +async function handleCloseTicketsAutomatic() { + const job = new CronJob('*/1 * * * *', async () => { + const companies = await Company.findAll(); + companies.map(async c => { + + try { + const companyId = c.id; + await ClosedAllOpenTickets(companyId); + } catch (e: any) { + Sentry.captureException(e); + logger.error("ClosedAllOpenTickets -> Verify: error", e.message); + throw e; + } + + }); + }); + job.start() +} + +async function handleVerifySchedules(job) { + try { + const { count, rows: schedules } = await Schedule.findAndCountAll({ + where: { + status: "PENDENTE", + sentAt: null, + sendAt: { + [Op.gte]: moment().format("YYYY-MM-DD HH:mm:ss"), + [Op.lte]: moment().add("30", "seconds").format("YYYY-MM-DD HH:mm:ss") + } + }, + include: [{ model: Contact, as: "contact" }] + }); + if (count > 0) { + schedules.map(async schedule => { + await schedule.update({ + status: "AGENDADA" + }); + sendScheduledMessages.add( + "SendMessage", + { schedule }, + { delay: 40000 } + ); + logger.info(`Disparo agendado para: ${schedule.contact.name}`); + }); + } + } catch (e: any) { + Sentry.captureException(e); + logger.error("SendScheduledMessage -> Verify: error", e.message); + throw e; + } +} + +async function handleSendScheduledMessage(job) { + const { + data: { schedule } + } = job; + let scheduleRecord: Schedule | null = null; + + try { + scheduleRecord = await Schedule.findByPk(schedule.id); + } catch (e) { + Sentry.captureException(e); + logger.info(`Erro ao tentar consultar agendamento: ${schedule.id}`); + } + + try { + const whatsapp = await GetDefaultWhatsApp(schedule.companyId); + + let filePath = null; + if (schedule.mediaPath) { + filePath = path.resolve("public", `company${schedule.companyId}`, schedule.mediaPath); + } + + await SendMessage(whatsapp, { + number: schedule.contact.number, + body: formatBody(schedule.body, schedule.contact), + mediaPath: filePath + }); + + await scheduleRecord?.update({ + sentAt: moment().format("YYYY-MM-DD HH:mm"), + status: "ENVIADA" + }); + + logger.info(`Mensagem agendada enviada para: ${schedule.contact.name}`); + sendScheduledMessages.clean(15000, "completed"); + } catch (e: any) { + Sentry.captureException(e); + await scheduleRecord?.update({ + status: "ERRO" + }); + logger.error("SendScheduledMessage -> SendMessage: error", e.message); + throw e; + } +} + +async function handleVerifyCampaigns(job) { + /** + * @todo + * Implementar filtro de campanhas + */ + const campaigns: { id: number; scheduledAt: string }[] = + await sequelize.query( + `select id, "scheduledAt" from "Campaigns" c + where "scheduledAt" between now() and now() + '1 hour'::interval and status = 'PROGRAMADA'`, + { type: QueryTypes.SELECT } + ); + + if (campaigns.length > 0) + logger.info(`Campanhas encontradas: ${campaigns.length}`); + + for (let campaign of campaigns) { + try { + const now = moment(); + const scheduledAt = moment(campaign.scheduledAt); + const delay = scheduledAt.diff(now, "milliseconds"); + logger.info( + `Campanha enviada para a fila de processamento: Campanha=${campaign.id}, Delay Inicial=${delay}` + ); + campaignQueue.add( + "ProcessCampaign", + { + id: campaign.id, + delay + }, + { + removeOnComplete: true + } + ); + } catch (err: any) { + Sentry.captureException(err); + } + } +} + +async function getCampaign(id) { + return await Campaign.findByPk(id, { + include: [ + { + model: ContactList, + as: "contactList", + attributes: ["id", "name"], + include: [ + { + model: ContactListItem, + as: "contacts", + attributes: ["id", "name", "number", "email", "isWhatsappValid"], + where: { isWhatsappValid: true } + } + ] + }, + { + model: Whatsapp, + as: "whatsapp", + attributes: ["id", "name"] + }, + { + model: CampaignShipping, + as: "shipping", + include: [{ model: ContactListItem, as: "contact" }] + } + ] + }); +} + +async function getContact(id) { + return await ContactListItem.findByPk(id, { + attributes: ["id", "name", "number", "email"] + }); +} + +async function getSettings(campaign) { + const settings = await CampaignSetting.findAll({ + where: { companyId: campaign.companyId }, + attributes: ["key", "value"] + }); + + let messageInterval: number = 20; + let longerIntervalAfter: number = 20; + let greaterInterval: number = 60; + let variables: any[] = []; + + settings.forEach(setting => { + if (setting.key === "messageInterval") { + messageInterval = JSON.parse(setting.value); + } + if (setting.key === "longerIntervalAfter") { + longerIntervalAfter = JSON.parse(setting.value); + } + if (setting.key === "greaterInterval") { + greaterInterval = JSON.parse(setting.value); + } + if (setting.key === "variables") { + variables = JSON.parse(setting.value); + } + }); + + return { + messageInterval, + longerIntervalAfter, + greaterInterval, + variables + }; +} + +export function parseToMilliseconds(seconds) { + return seconds * 1000; +} + +async function sleep(seconds) { + logger.info( + `Sleep de ${seconds} segundos iniciado: ${moment().format("HH:mm:ss")}` + ); + return new Promise(resolve => { + setTimeout(() => { + logger.info( + `Sleep de ${seconds} segundos finalizado: ${moment().format( + "HH:mm:ss" + )}` + ); + resolve(true); + }, parseToMilliseconds(seconds)); + }); +} + +function getCampaignValidMessages(campaign) { + const messages = []; + + if (!isEmpty(campaign.message1) && !isNil(campaign.message1)) { + messages.push(campaign.message1); + } + + if (!isEmpty(campaign.message2) && !isNil(campaign.message2)) { + messages.push(campaign.message2); + } + + if (!isEmpty(campaign.message3) && !isNil(campaign.message3)) { + messages.push(campaign.message3); + } + + if (!isEmpty(campaign.message4) && !isNil(campaign.message4)) { + messages.push(campaign.message4); + } + + if (!isEmpty(campaign.message5) && !isNil(campaign.message5)) { + messages.push(campaign.message5); + } + + return messages; +} + +function getCampaignValidConfirmationMessages(campaign) { + const messages = []; + + if ( + !isEmpty(campaign.confirmationMessage1) && + !isNil(campaign.confirmationMessage1) + ) { + messages.push(campaign.confirmationMessage1); + } + + if ( + !isEmpty(campaign.confirmationMessage2) && + !isNil(campaign.confirmationMessage2) + ) { + messages.push(campaign.confirmationMessage2); + } + + if ( + !isEmpty(campaign.confirmationMessage3) && + !isNil(campaign.confirmationMessage3) + ) { + messages.push(campaign.confirmationMessage3); + } + + if ( + !isEmpty(campaign.confirmationMessage4) && + !isNil(campaign.confirmationMessage4) + ) { + messages.push(campaign.confirmationMessage4); + } + + if ( + !isEmpty(campaign.confirmationMessage5) && + !isNil(campaign.confirmationMessage5) + ) { + messages.push(campaign.confirmationMessage5); + } + + return messages; +} + +function getProcessedMessage(msg: string, variables: any[], contact: any) { + let finalMessage = msg; + + if (finalMessage.includes("{nome}")) { + finalMessage = finalMessage.replace(/{nome}/g, contact.name); + } + + if (finalMessage.includes("{email}")) { + finalMessage = finalMessage.replace(/{email}/g, contact.email); + } + + if (finalMessage.includes("{numero}")) { + finalMessage = finalMessage.replace(/{numero}/g, contact.number); + } + + variables.forEach(variable => { + if (finalMessage.includes(`{${variable.key}}`)) { + const regex = new RegExp(`{${variable.key}}`, "g"); + finalMessage = finalMessage.replace(regex, variable.value); + } + }); + + return finalMessage; +} + +export function randomValue(min, max) { + return Math.floor(Math.random() * max) + min; +} + +async function verifyAndFinalizeCampaign(campaign) { + const { contacts } = campaign.contactList; + + const count1 = contacts.length; + const count2 = await CampaignShipping.count({ + where: { + campaignId: campaign.id, + deliveredAt: { + [Op.not]: null + } + } + }); + + if (count1 === count2) { + await campaign.update({ status: "FINALIZADA", completedAt: moment() }); + } + + const io = getIO(); + io.to(`company-${campaign.companyId}-mainchannel`).emit(`company-${campaign.companyId}-campaign`, { + action: "update", + record: campaign + }); +} + +function calculateDelay(index, baseDelay, longerIntervalAfter, greaterInterval, messageInterval) { + const diffSeconds = differenceInSeconds(baseDelay, new Date()); + if (index > longerIntervalAfter) { + return diffSeconds * 1000 + greaterInterval + } else { + return diffSeconds * 1000 + messageInterval + } +} + +async function handleProcessCampaign(job) { + try { + const { id }: ProcessCampaignData = job.data; + const campaign = await getCampaign(id); + const settings = await getSettings(campaign); + if (campaign) { + const { contacts } = campaign.contactList; + if (isArray(contacts)) { + const contactData = contacts.map(contact => ({ + contactId: contact.id, + campaignId: campaign.id, + variables: settings.variables, + })); + + // const baseDelay = job.data.delay || 0; + const longerIntervalAfter = parseToMilliseconds(settings.longerIntervalAfter); + const greaterInterval = parseToMilliseconds(settings.greaterInterval); + const messageInterval = settings.messageInterval; + + let baseDelay = campaign.scheduledAt; + + const queuePromises = []; + for (let i = 0; i < contactData.length; i++) { + baseDelay = addSeconds(baseDelay, i > longerIntervalAfter ? greaterInterval : messageInterval); + + const { contactId, campaignId, variables } = contactData[i]; + const delay = calculateDelay(i, baseDelay, longerIntervalAfter, greaterInterval, messageInterval); + const queuePromise = campaignQueue.add( + "PrepareContact", + { contactId, campaignId, variables, delay }, + { removeOnComplete: true } + ); + queuePromises.push(queuePromise); + logger.info(`Registro enviado pra fila de disparo: Campanha=${campaign.id};Contato=${contacts[i].name};delay=${delay}`); + } + await Promise.all(queuePromises); + await campaign.update({ status: "EM_ANDAMENTO" }); + } + } + } catch (err: any) { + Sentry.captureException(err); + } +} + +let ultima_msg = 0; +async function handlePrepareContact(job) { + try { + const { contactId, campaignId, delay, variables }: PrepareContactData = + job.data; + const campaign = await getCampaign(campaignId); + const contact = await getContact(contactId); + + const campaignShipping: any = {}; + campaignShipping.number = contact.number; + campaignShipping.contactId = contactId; + campaignShipping.campaignId = campaignId; + + const messages = getCampaignValidMessages(campaign); + if (messages.length) { + const radomIndex = ultima_msg; + console.log('ultima_msg:', ultima_msg); + ultima_msg++; + if (ultima_msg >= messages.length) { + ultima_msg = 0; + } + const message = getProcessedMessage( + messages[radomIndex], + variables, + contact + ); + campaignShipping.message = `\u200c ${message}`; + } + + if (campaign.confirmation) { + const confirmationMessages = + getCampaignValidConfirmationMessages(campaign); + if (confirmationMessages.length) { + const radomIndex = randomValue(0, confirmationMessages.length); + const message = getProcessedMessage( + confirmationMessages[radomIndex], + variables, + contact + ); + campaignShipping.confirmationMessage = `\u200c ${message}`; + } + } + + const [record, created] = await CampaignShipping.findOrCreate({ + where: { + campaignId: campaignShipping.campaignId, + contactId: campaignShipping.contactId + }, + defaults: campaignShipping + }); + + if ( + !created && + record.deliveredAt === null && + record.confirmationRequestedAt === null + ) { + record.set(campaignShipping); + await record.save(); + } + + if ( + record.deliveredAt === null && + record.confirmationRequestedAt === null + ) { + const nextJob = await campaignQueue.add( + "DispatchCampaign", + { + campaignId: campaign.id, + campaignShippingId: record.id, + contactListItemId: contactId + }, + { + delay + } + ); + + await record.update({ jobId: nextJob.id }); + } + + await verifyAndFinalizeCampaign(campaign); + } catch (err: any) { + Sentry.captureException(err); + logger.error(`campaignQueue -> PrepareContact -> error: ${err.message}`); + } +} + +async function handleDispatchCampaign(job) { + try { + const { data } = job; + const { campaignShippingId, campaignId }: DispatchCampaignData = data; + const campaign = await getCampaign(campaignId); + const wbot = await GetWhatsappWbot(campaign.whatsapp); + + if (!wbot) { + logger.error(`campaignQueue -> DispatchCampaign -> error: wbot not found`); + return; + } + + if (!campaign.whatsapp) { + logger.error(`campaignQueue -> DispatchCampaign -> error: whatsapp not found`); + return; + } + + if (!wbot?.user?.id) { + logger.error(`campaignQueue -> DispatchCampaign -> error: wbot user not found`); + return; + } + + logger.info( + `Disparo de campanha solicitado: Campanha=${campaignId};Registro=${campaignShippingId}` + ); + + const campaignShipping = await CampaignShipping.findByPk( + campaignShippingId, + { + include: [{ model: ContactListItem, as: "contact" }] + } + ); + + const chatId = `${campaignShipping.number}@s.whatsapp.net`; + + let body = campaignShipping.message; + + if (campaign.confirmation && campaignShipping.confirmation === null) { + body = campaignShipping.confirmationMessage + } + + if (!isNil(campaign.fileListId)) { + try { + const publicFolder = path.resolve(__dirname, "..", "public"); + const files = await ShowFileService(campaign.fileListId, campaign.companyId) + const folder = path.resolve(publicFolder, "fileList", String(files.id)) + for (const [index, file] of files.options.entries()) { + const options = await getMessageOptions(file.path, path.resolve(folder, file.path), file.name); + await wbot.sendMessage(chatId, { ...options }); + }; + } catch (error) { + logger.info(error); + } + } + + if (campaign.mediaPath) { + const publicFolder = path.resolve(__dirname, "..", "public"); + const filePath = path.join(publicFolder, `company${campaign.companyId}`, campaign.mediaPath); + + console.log("Body antes de getMessageOptions:", body); // Verifica se o texto está aqui + + //const options = await getMessageOptions(campaign.mediaName, filePath, body); + const options = await getMessageOptions(campaign.mediaName, filePath, String(campaign.companyId), body); // 4 argumentos + console.log("Options retornadas:", options); // Verifica se o caption está no options + + if (Object.keys(options).length) { + await wbot.sendMessage(chatId, { ...options }); + } + } + else { + if (campaign.confirmation && campaignShipping.confirmation === null) { + await wbot.sendMessage(chatId, { + text: body + }); + await campaignShipping.update({ confirmationRequestedAt: moment() }); + } else { + + await wbot.sendMessage(chatId, { + text: body + }); + } + } + await campaignShipping.update({ deliveredAt: moment() }); + + await verifyAndFinalizeCampaign(campaign); + + const io = getIO(); + io.to(`company-${campaign.companyId}-mainchannel`).emit(`company-${campaign.companyId}-campaign`, { + action: "update", + record: campaign + }); + + logger.info( + `Campanha enviada para: Campanha=${campaignId};Contato=${campaignShipping.contact.name}` + ); + } catch (err: any) { + Sentry.captureException(err); + logger.error(err.message); + console.log(err.stack); + } +} + +async function handleLoginStatus(job) { + const users: { id: number }[] = await sequelize.query( + `select id from "Users" where "updatedAt" < now() - '5 minutes'::interval and online = true`, + { type: QueryTypes.SELECT } + ); + for (let item of users) { + try { + const user = await User.findByPk(item.id); + await user.update({ online: false }); + logger.info(`Usuário passado para offline: ${item.id}`); + } catch (e: any) { + Sentry.captureException(e); + } + } +} + + +async function handleInvoiceCreate() { + logger.info("GERENDO RECEITA..."); + const job = new CronJob('*/5 * * * * *', async () => { + const companies = await Company.findAll(); + companies.map(async c => { + + const status = c.status; + const dueDate = c.dueDate; + const date = moment(dueDate).format(); + const timestamp = moment().format(); + const hoje = moment().format("DD/MM/yyyy"); + const vencimento = moment(dueDate).format("DD/MM/yyyy"); + const diff = moment(vencimento, "DD/MM/yyyy").diff(moment(hoje, "DD/MM/yyyy")); + const dias = moment.duration(diff).asDays(); + + if(status === true){ + + //logger.info(`EMPRESA: ${c.id} está ATIVA com vencimento em: ${vencimento} | ${dias}`); + + //Verifico se a empresa está a mais de 10 dias sem pagamento + + if(dias <= -3){ + + logger.info(`EMPRESA: ${c.id} está VENCIDA A MAIS DE 3 DIAS... INATIVANDO... ${dias}`); + c.status = false; + await c.save(); // Save the updated company record + logger.info(`EMPRESA: ${c.id} foi INATIVADA.`); + logger.info(`EMPRESA: ${c.id} Desativando conexões com o WhatsApp...`); + + try { + const whatsapps = await Whatsapp.findAll({ + where: { + companyId: c.id, + }, + attributes: ['id','status','session'], + }); + + for (const whatsapp of whatsapps) { + + if (whatsapp.session) { + await whatsapp.update({ status: "DISCONNECTED", session: "" }); + const wbot = getWbot(whatsapp.id); + await wbot.logout(); + logger.info(`EMPRESA: ${c.id} teve o WhatsApp ${whatsapp.id} desconectado...`); + } + } + + } catch (error) { + // Lidar com erros, se houver + console.error('Erro ao buscar os IDs de WhatsApp:', error); + throw error; + } + + + }else{ // ELSE if(dias <= -3){ + + const plan = await Plan.findByPk(c.planId); + + const sql = `SELECT * FROM "Invoices" WHERE "companyId" = ${c.id} AND "status" = 'open';` + const openInvoices = await sequelize.query(sql, { type: QueryTypes.SELECT }) as { id: number, dueDate: Date }[]; + + const existingInvoice = openInvoices.find(invoice => moment(invoice.dueDate).format("DD/MM/yyyy") === vencimento); + + if (existingInvoice) { + // Due date already exists, no action needed + //logger.info(`Fatura Existente`); + + } else if (openInvoices.length > 0) { + const updateSql = `UPDATE "Invoices" SET "dueDate" = '${date}', "updatedAt" = '${timestamp}' WHERE "id" = ${openInvoices[0].id};`; + + await sequelize.query(updateSql, { type: QueryTypes.UPDATE }); + + logger.info(`Fatura Atualizada ID: ${openInvoices[0].id}`); + + } else { + + const sql = `INSERT INTO "Invoices" (detail, status, value, "updatedAt", "createdAt", "dueDate", "companyId") + VALUES ('${plan.name}', 'open', '${plan.value}', '${timestamp}', '${timestamp}', '${date}', ${c.id});` + + const invoiceInsert = await sequelize.query(sql, { type: QueryTypes.INSERT }); + + logger.info(`Fatura Gerada para o cliente: ${c.id}`); + + // Rest of the code for sending email + } + + + + + } // if(dias <= -6){ + + + }else{ // ELSE if(status === true){ + + //logger.info(`EMPRESA: ${c.id} está INATIVA`); + + } + + + + }); + }); + + job.start(); +} + + + +handleCloseTicketsAutomatic() + +handleInvoiceCreate() + +export async function startQueueProcess() { + logger.info("Iniciando processamento de filas"); + + messageQueue.process("SendMessage", handleSendMessage); + + scheduleMonitor.process("Verify", handleVerifySchedules); + + sendScheduledMessages.process("SendMessage", handleSendScheduledMessage); + + campaignQueue.process("VerifyCampaigns", handleVerifyCampaigns); + + campaignQueue.process("ProcessCampaign", handleProcessCampaign); + + campaignQueue.process("PrepareContact", handlePrepareContact); + + campaignQueue.process("DispatchCampaign", handleDispatchCampaign); + + userMonitor.process("VerifyLoginStatus", handleLoginStatus); + + //queueMonitor.process("VerifyQueueStatus", handleVerifyQueue); + + + + scheduleMonitor.add( + "Verify", + {}, + { + repeat: { cron: "*/5 * * * * *", key: "verify" }, + removeOnComplete: true + } + ); + + campaignQueue.add( + "VerifyCampaigns", + {}, + { + repeat: { cron: "*/20 * * * * *", key: "verify-campaing" }, + removeOnComplete: true + } + ); + + userMonitor.add( + "VerifyLoginStatus", + {}, + { + repeat: { cron: "* * * * *", key: "verify-login" }, + removeOnComplete: true + } + ); + + queueMonitor.add( + "VerifyQueueStatus", + {}, + { + repeat: { cron: "*/20 * * * * *" }, + removeOnComplete: true + } + ); +} diff --git a/backend/src/routes/announcementRoutes.ts b/backend/src/routes/announcementRoutes.ts new file mode 100644 index 0000000..3b64f0d --- /dev/null +++ b/backend/src/routes/announcementRoutes.ts @@ -0,0 +1,38 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; +import isSuper from "../middleware/isSuper"; + +import * as AnnouncementController from "../controllers/AnnouncementController"; +import multer from "multer"; +import uploadConfig from "../config/upload"; + +const upload = multer(uploadConfig); + +const routes = express.Router(); + +routes.get("/announcements/list", isAuth, AnnouncementController.findList); + +routes.get("/announcements", isAuth, AnnouncementController.index); + +routes.get("/announcements/:id", isAuth, AnnouncementController.show); + +routes.post("/announcements", isAuth, isSuper, AnnouncementController.store); + +routes.put("/announcements/:id", isAuth, isSuper, AnnouncementController.update); + +routes.delete("/announcements/:id", isAuth, isSuper, AnnouncementController.remove); + +routes.post( + "/announcements/:id/media-upload", + isAuth, isSuper, + upload.array("file"), + AnnouncementController.mediaUpload +); + +routes.delete( + "/announcements/:id/media-upload", + isAuth, isSuper, + AnnouncementController.deleteMedia +); + +export default routes; diff --git a/backend/src/routes/authRoutes.ts b/backend/src/routes/authRoutes.ts new file mode 100644 index 0000000..8a5c3b0 --- /dev/null +++ b/backend/src/routes/authRoutes.ts @@ -0,0 +1,15 @@ +import { Router } from "express"; +import * as SessionController from "../controllers/SessionController"; +import * as UserController from "../controllers/UserController"; +import isAuth from "../middleware/isAuth"; +import envTokenAuth from "../middleware/envTokenAuth"; + +const authRoutes = Router(); + +authRoutes.post("/signup", envTokenAuth, UserController.store); +authRoutes.post("/login", SessionController.store); +authRoutes.post("/refresh_token", SessionController.update); +authRoutes.delete("/logout", isAuth, SessionController.remove); +authRoutes.get("/me", isAuth, SessionController.me); + +export default authRoutes; diff --git a/backend/src/routes/campaignRoutes.ts b/backend/src/routes/campaignRoutes.ts new file mode 100644 index 0000000..2a794fd --- /dev/null +++ b/backend/src/routes/campaignRoutes.ts @@ -0,0 +1,41 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; + +import * as CampaignController from "../controllers/CampaignController"; +import multer from "multer"; +import uploadConfig from "../config/upload"; + +const upload = multer(uploadConfig); + +const routes = express.Router(); + +routes.get("/campaigns/list", isAuth, CampaignController.findList); + +routes.get("/campaigns", isAuth, CampaignController.index); + +routes.get("/campaigns/:id", isAuth, CampaignController.show); + +routes.post("/campaigns", isAuth, CampaignController.store); + +routes.put("/campaigns/:id", isAuth, CampaignController.update); + +routes.delete("/campaigns/:id", isAuth, CampaignController.remove); + +routes.post("/campaigns/:id/cancel", isAuth, CampaignController.cancel); + +routes.post("/campaigns/:id/restart", isAuth, CampaignController.restart); + +routes.post( + "/campaigns/:id/media-upload", + isAuth, + upload.array("file"), + CampaignController.mediaUpload +); + +routes.delete( + "/campaigns/:id/media-upload", + isAuth, + CampaignController.deleteMedia +); + +export default routes; diff --git a/backend/src/routes/campaignSettingRoutes.ts b/backend/src/routes/campaignSettingRoutes.ts new file mode 100644 index 0000000..572ea57 --- /dev/null +++ b/backend/src/routes/campaignSettingRoutes.ts @@ -0,0 +1,16 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; + +import * as CampaignSettingController from "../controllers/CampaignSettingController"; +import multer from "multer"; +import uploadConfig from "../config/upload"; + +const upload = multer(uploadConfig); + +const routes = express.Router(); + +routes.get("/campaign-settings", isAuth, CampaignSettingController.index); + +routes.post("/campaign-settings", isAuth, CampaignSettingController.store); + +export default routes; diff --git a/backend/src/routes/chatRoutes.ts b/backend/src/routes/chatRoutes.ts new file mode 100644 index 0000000..1d27994 --- /dev/null +++ b/backend/src/routes/chatRoutes.ts @@ -0,0 +1,24 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; + +import * as ChatController from "../controllers/ChatController"; + +const routes = express.Router(); + +routes.get("/chats", isAuth, ChatController.index); + +routes.get("/chats/:id", isAuth, ChatController.show); + +routes.get("/chats/:id/messages", isAuth, ChatController.messages); + +routes.post("/chats/:id/messages", isAuth, ChatController.saveMessage); + +routes.post("/chats/:id/read", isAuth, ChatController.checkAsRead); + +routes.post("/chats", isAuth, ChatController.store); + +routes.put("/chats/:id", isAuth, ChatController.update); + +routes.delete("/chats/:id", isAuth, ChatController.remove); + +export default routes; diff --git a/backend/src/routes/companyRoutes.ts b/backend/src/routes/companyRoutes.ts new file mode 100644 index 0000000..99aa631 --- /dev/null +++ b/backend/src/routes/companyRoutes.ts @@ -0,0 +1,22 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; +import isSuper from "../middleware/isSuper"; + +import * as CompanyController from "../controllers/CompanyController"; + +const companyRoutes = express.Router(); + +companyRoutes.get("/companies/list", isAuth, isSuper, CompanyController.list); +companyRoutes.get("/companies", isAuth, isSuper, CompanyController.index); +companyRoutes.get("/companies/:id", isAuth, CompanyController.show); +companyRoutes.post("/companies", isAuth, isSuper, CompanyController.store); +companyRoutes.put("/companies/:id", isAuth, isSuper, CompanyController.update); +companyRoutes.put("/companies/:id/schedules",isAuth,CompanyController.updateSchedules); +companyRoutes.delete("/companies/:id", isAuth, isSuper, CompanyController.remove); +companyRoutes.post("/companies/cadastro", CompanyController.store); + +// Rota para listar o plano da empresa +companyRoutes.get("/companies/listPlan/:id", isAuth, CompanyController.listPlan); +companyRoutes.get("/companiesPlan", isAuth, CompanyController.indexPlan); + +export default companyRoutes; diff --git a/backend/src/routes/contactListItemRoutes.ts b/backend/src/routes/contactListItemRoutes.ts new file mode 100644 index 0000000..7f91592 --- /dev/null +++ b/backend/src/routes/contactListItemRoutes.ts @@ -0,0 +1,28 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; + +import * as ContactListItemController from "../controllers/ContactListItemController"; + +const routes = express.Router(); + +routes.get( + "/contact-list-items/list", + isAuth, + ContactListItemController.findList +); + +routes.get("/contact-list-items", isAuth, ContactListItemController.index); + +routes.get("/contact-list-items/:id", isAuth, ContactListItemController.show); + +routes.post("/contact-list-items", isAuth, ContactListItemController.store); + +routes.put("/contact-list-items/:id", isAuth, ContactListItemController.update); + +routes.delete( + "/contact-list-items/:id", + isAuth, + ContactListItemController.remove +); + +export default routes; diff --git a/backend/src/routes/contactListRoutes.ts b/backend/src/routes/contactListRoutes.ts new file mode 100644 index 0000000..574e567 --- /dev/null +++ b/backend/src/routes/contactListRoutes.ts @@ -0,0 +1,31 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; +import uploadConfig from "../config/upload"; + +import * as ContactListController from "../controllers/ContactListController"; +import multer from "multer"; + +const routes = express.Router(); + +const upload = multer(uploadConfig); + +routes.get("/contact-lists/list", isAuth, ContactListController.findList); + +routes.get("/contact-lists", isAuth, ContactListController.index); + +routes.get("/contact-lists/:id", isAuth, ContactListController.show); + +routes.post("/contact-lists", isAuth, ContactListController.store); + +routes.post( + "/contact-lists/:id/upload", + isAuth, + upload.array("file"), + ContactListController.upload +); + +routes.put("/contact-lists/:id", isAuth, ContactListController.update); + +routes.delete("/contact-lists/:id", isAuth, ContactListController.remove); + +export default routes; diff --git a/backend/src/routes/contactRoutes.ts b/backend/src/routes/contactRoutes.ts new file mode 100644 index 0000000..128091c --- /dev/null +++ b/backend/src/routes/contactRoutes.ts @@ -0,0 +1,43 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; + +import * as ContactController from "../controllers/ContactController"; +import * as ImportPhoneContactsController from "../controllers/ImportPhoneContactsController"; +import routes from "./contactListRoutes"; +import uploadConfig from "../config/upload"; +import multer from "multer"; + +const contactRoutes = express.Router(); + +const upload = multer(uploadConfig); + +contactRoutes.post( + "/contacts/import", + isAuth, + ImportPhoneContactsController.store +); + +routes.post( + "/contacts/upload", + isAuth, + upload.array("file"), + ContactController.upload +); + +contactRoutes.get("/contacts", isAuth, ContactController.index); + +contactRoutes.get("/contacts/list", isAuth, ContactController.list); + +contactRoutes.get("/contacts/:contactId", isAuth, ContactController.show); + +contactRoutes.post("/contacts", isAuth, ContactController.store); + +contactRoutes.put("/contacts/:contactId", isAuth, ContactController.update); + +contactRoutes.delete("/contacts/:contactId", isAuth, ContactController.remove); + +contactRoutes.get("/contact", isAuth, ContactController.getContactVcard); + + + +export default contactRoutes; diff --git a/backend/src/routes/dashboardRoutes.ts b/backend/src/routes/dashboardRoutes.ts new file mode 100644 index 0000000..3f91342 --- /dev/null +++ b/backend/src/routes/dashboardRoutes.ts @@ -0,0 +1,12 @@ +import express from 'express'; +import isAuth from '../middleware/isAuth'; + +import * as DashboardController from '../controllers/DashbardController'; + +const routes = express.Router(); + +routes.get('/dashboard', isAuth, DashboardController.index); +routes.get('/dashboard/ticketsUsers', DashboardController.reportsUsers); +routes.get('/dashboard/ticketsDay', DashboardController.reportsDay); + +export default routes; diff --git a/backend/src/routes/filesRoutes.ts b/backend/src/routes/filesRoutes.ts new file mode 100644 index 0000000..1b2814c --- /dev/null +++ b/backend/src/routes/filesRoutes.ts @@ -0,0 +1,20 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; +import uploadConfig from "../config/upload"; +import multer from "multer"; + +import * as FilesController from "../controllers/FilesController"; + +const upload = multer(uploadConfig); + +const filesRoutes = express.Router(); + +filesRoutes.get("/files/list", isAuth, FilesController.list); +filesRoutes.get("/files", isAuth, FilesController.index); +filesRoutes.post("/files", isAuth, FilesController.store); +filesRoutes.put("/files/:fileId", isAuth, FilesController.update); +filesRoutes.get("/files/:fileId", isAuth, FilesController.show); +filesRoutes.delete("/files/:fileId", isAuth, FilesController.remove); +filesRoutes.delete("/files", isAuth, FilesController.removeAll); +filesRoutes.post("/files/uploadList/:fileListId", isAuth, upload.array("files"), FilesController.uploadMedias); +export default filesRoutes; diff --git a/backend/src/routes/forgotPasswordRoutes.ts b/backend/src/routes/forgotPasswordRoutes.ts new file mode 100644 index 0000000..5fae897 --- /dev/null +++ b/backend/src/routes/forgotPasswordRoutes.ts @@ -0,0 +1,10 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; +import * as ForgotController from "../controllers/ForgotController"; +const forgotsRoutes = express.Router(); +forgotsRoutes.post("/forgetpassword/:email", ForgotController.store); +forgotsRoutes.post( + "/resetpasswords/:email/:token/:password", + ForgotController.resetPasswords +); +export default forgotsRoutes; diff --git a/backend/src/routes/helpRoutes.ts b/backend/src/routes/helpRoutes.ts new file mode 100644 index 0000000..c3c4512 --- /dev/null +++ b/backend/src/routes/helpRoutes.ts @@ -0,0 +1,21 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; +import isSuper from "../middleware/isSuper"; + +import * as HelpController from "../controllers/HelpController"; + +const routes = express.Router(); + +routes.get("/helps/list", isAuth, HelpController.findList); + +routes.get("/helps", isAuth, HelpController.index); + +routes.get("/helps/:id", isAuth, HelpController.show); + +routes.post("/helps", isAuth, isSuper, HelpController.store); + +routes.put("/helps/:id", isAuth, isSuper, HelpController.update); + +routes.delete("/helps/:id", isAuth, isSuper, HelpController.remove); + +export default routes; diff --git a/backend/src/routes/hubChannelRoutes.ts b/backend/src/routes/hubChannelRoutes.ts new file mode 100644 index 0000000..e31dbf8 --- /dev/null +++ b/backend/src/routes/hubChannelRoutes.ts @@ -0,0 +1,11 @@ +import express from "express"; + +import * as ChannelController from "../controllers/ChannelHubController"; +import isAuth from "../middleware/isAuth"; + +const hubChannelRoutes = express.Router(); + +hubChannelRoutes.post("/hub-channel/", isAuth, ChannelController.store); +hubChannelRoutes.get("/hub-channel/", isAuth, ChannelController.index); + +export default hubChannelRoutes; \ No newline at end of file diff --git a/backend/src/routes/hubMessageRoutes.ts b/backend/src/routes/hubMessageRoutes.ts new file mode 100644 index 0000000..f7e6b2c --- /dev/null +++ b/backend/src/routes/hubMessageRoutes.ts @@ -0,0 +1,14 @@ +import express from "express"; +import uploadConfig from "../config/upload"; +import isAuth from "../middleware/isAuth"; +import multer from "multer"; + +import * as MessageController from "../controllers/MessageHubController"; + +const hubMessageRoutes = express.Router(); +const upload = multer(uploadConfig); + +hubMessageRoutes.post("/hub-message/:ticketId",isAuth,upload.array("medias"),MessageController.send); +hubMessageRoutes.post("/hub-ticket", isAuth, MessageController.store); + +export default hubMessageRoutes; \ No newline at end of file diff --git a/backend/src/routes/hubNotificaMeRoutes.ts b/backend/src/routes/hubNotificaMeRoutes.ts new file mode 100644 index 0000000..61fabf4 --- /dev/null +++ b/backend/src/routes/hubNotificaMeRoutes.ts @@ -0,0 +1,19 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; // Autenticação do usuário +import * as HubNotificaMeController from "../controllers/HubNotificaMeController"; // Adaptado para o controlador de HubNotificaMe + +const routes = express.Router(); + +// Rota para listar HubNotificaMe (apenas registros do usuário e empresa da sessão) +routes.get("/hub-notificame/list", isAuth, HubNotificaMeController.findList); + +// Rota para criar um novo HubNotificaMe +routes.post("/hub-notificame", isAuth, HubNotificaMeController.store); + +// Rota para atualizar um HubNotificaMe existente +routes.put("/hub-notificame/:id", isAuth, HubNotificaMeController.update); + +// Rota para deletar um HubNotificaMe +routes.delete("/hub-notificame/:id", isAuth, HubNotificaMeController.remove); + +export default routes; diff --git a/backend/src/routes/hubWebhookRoutes.ts b/backend/src/routes/hubWebhookRoutes.ts new file mode 100644 index 0000000..77bab74 --- /dev/null +++ b/backend/src/routes/hubWebhookRoutes.ts @@ -0,0 +1,16 @@ +import express from "express"; +import uploadConfig from "../config/upload"; + +import * as WebhookController from "../controllers/WebhookHubController"; +import multer from "multer"; + +const hubWebhookRoutes = express.Router(); +const upload = multer(uploadConfig); + +hubWebhookRoutes.post( + "/hub-webhook/:channelId", + upload.array("medias"), + WebhookController.listen +); + +export default hubWebhookRoutes; \ No newline at end of file diff --git a/backend/src/routes/index.ts b/backend/src/routes/index.ts new file mode 100644 index 0000000..3a3c991 --- /dev/null +++ b/backend/src/routes/index.ts @@ -0,0 +1,86 @@ +import { Router } from "express"; + +import userRoutes from "./userRoutes"; +import authRoutes from "./authRoutes"; +import settingRoutes from "./settingRoutes"; +import contactRoutes from "./contactRoutes"; +import ticketRoutes from "./ticketRoutes"; +import whatsappRoutes from "./whatsappRoutes"; +import messageRoutes from "./messageRoutes"; +import whatsappSessionRoutes from "./whatsappSessionRoutes"; +import queueRoutes from "./queueRoutes"; +import companyRoutes from "./companyRoutes"; +import planRoutes from "./planRoutes"; +import ticketNoteRoutes from "./ticketNoteRoutes"; +import quickMessageRoutes from "./quickMessageRoutes"; +import helpRoutes from "./helpRoutes"; +import dashboardRoutes from "./dashboardRoutes"; +import queueOptionRoutes from "./queueOptionRoutes"; +import scheduleRoutes from "./scheduleRoutes"; +import tagRoutes from "./tagRoutes"; +import contactListRoutes from "./contactListRoutes"; +import contactListItemRoutes from "./contactListItemRoutes"; +import campaignRoutes from "./campaignRoutes"; +import campaignSettingRoutes from "./campaignSettingRoutes"; +import announcementRoutes from "./announcementRoutes"; +import chatRoutes from "./chatRoutes"; +import invoiceRoutes from "./invoicesRoutes"; +import subscriptionRoutes from "./subScriptionRoutes"; +import ticketTagRoutes from "./ticketTagRoutes"; +import filesRoutes from "./filesRoutes"; +import promptRoutes from "./promptRouter"; +import queueIntegrationRoutes from "./queueIntegrationRoutes"; +import forgotsRoutes from "./forgotPasswordRoutes"; +import versionRouter from "./versionRoutes"; +import reportsRoutes from './reportsRoutes'; + +import hubNotificaMeRoutes from "./hubNotificaMeRoutes"; + +import hubChannelRoutes from "./hubChannelRoutes"; +import hubMessageRoutes from "./hubMessageRoutes"; +import hubWebhookRoutes from "./hubWebhookRoutes"; + +const routes = Router(); + +routes.use(userRoutes); +routes.use("/auth", authRoutes); +routes.use(settingRoutes); +routes.use(contactRoutes); +routes.use(ticketRoutes); +routes.use(whatsappRoutes); +routes.use(messageRoutes); +routes.use(messageRoutes); +routes.use(whatsappSessionRoutes); +routes.use(queueRoutes); +routes.use(companyRoutes); +routes.use(planRoutes); +routes.use(ticketNoteRoutes); +routes.use(quickMessageRoutes); +routes.use(helpRoutes); +routes.use(dashboardRoutes); +routes.use(queueOptionRoutes); +routes.use(scheduleRoutes); +routes.use(tagRoutes); +routes.use(contactListRoutes); +routes.use(contactListItemRoutes); +routes.use(campaignRoutes); +routes.use(campaignSettingRoutes); +routes.use(announcementRoutes); +routes.use(chatRoutes); +routes.use(subscriptionRoutes); +routes.use(invoiceRoutes); +routes.use(ticketTagRoutes); +routes.use(filesRoutes); +routes.use(promptRoutes); +routes.use(queueIntegrationRoutes); +routes.use(forgotsRoutes); +routes.use(reportsRoutes); +routes.use(versionRouter); + +routes.use(hubNotificaMeRoutes); + +routes.use(hubChannelRoutes); +routes.use(hubMessageRoutes); +routes.use(hubWebhookRoutes); + +export default routes; \ No newline at end of file diff --git a/backend/src/routes/invoicesRoutes.ts b/backend/src/routes/invoicesRoutes.ts new file mode 100644 index 0000000..e1ffef0 --- /dev/null +++ b/backend/src/routes/invoicesRoutes.ts @@ -0,0 +1,14 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; +import * as QueueOptionController from "../controllers/QueueOptionController"; +import * as InvoicesController from "../controllers/InvoicesController" + +const invoiceRoutes = express.Router(); + +invoiceRoutes.get("/invoices", isAuth, InvoicesController.index); +invoiceRoutes.get("/invoices/list", InvoicesController.list); +invoiceRoutes.get("/invoices/all", isAuth, InvoicesController.list); +invoiceRoutes.get("/invoices/:Invoiceid", isAuth, InvoicesController.show); +invoiceRoutes.put("/invoices/:id", isAuth, InvoicesController.update); + +export default invoiceRoutes; diff --git a/backend/src/routes/messageRoutes.ts b/backend/src/routes/messageRoutes.ts new file mode 100644 index 0000000..a243035 --- /dev/null +++ b/backend/src/routes/messageRoutes.ts @@ -0,0 +1,22 @@ +import { Router } from "express"; +import multer from "multer"; +import isAuth from "../middleware/isAuth"; +import uploadConfig from "../config/upload"; +import tokenAuth from "../middleware/tokenAuth"; + +import * as MessageController from "../controllers/MessageController"; + +const messageRoutes = Router(); + +const upload = multer(uploadConfig); + +messageRoutes.get("/messages/:ticketId", isAuth, MessageController.index); +messageRoutes.post("/messages/:ticketId", isAuth, upload.array("medias"), MessageController.store); +messageRoutes.delete("/messages/:messageId", isAuth, MessageController.remove); +messageRoutes.post("/api/messages/send", tokenAuth, upload.array("medias"), MessageController.send); +messageRoutes.post("/messages/edit/:messageId", isAuth, MessageController.edit); +messageRoutes.post('/message/forward', isAuth, MessageController.forwardMessage) +messageRoutes.post('/messages/:messageId/reactions', isAuth, MessageController.addReaction); + + +export default messageRoutes; diff --git a/backend/src/routes/planRoutes.ts b/backend/src/routes/planRoutes.ts new file mode 100644 index 0000000..679b9ba --- /dev/null +++ b/backend/src/routes/planRoutes.ts @@ -0,0 +1,25 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; +import isSuper from "../middleware/isSuper"; + +import * as PlanController from "../controllers/PlanController"; + +const planRoutes = express.Router(); + +planRoutes.get("/plans", isAuth, PlanController.index); + +planRoutes.get("/plans/list", PlanController.list); + +planRoutes.get("/plans/all", PlanController.list); + +planRoutes.get("/plans/register", PlanController.register); + +planRoutes.get("/plans/:id", isAuth, PlanController.show); + +planRoutes.post("/plans", isAuth, isSuper, PlanController.store); + +planRoutes.put("/plans/:id", isAuth, isSuper, PlanController.update); + +planRoutes.delete("/plans/:id", isAuth, isSuper, PlanController.remove); + +export default planRoutes; diff --git a/backend/src/routes/promptRouter.ts b/backend/src/routes/promptRouter.ts new file mode 100644 index 0000000..1b140a6 --- /dev/null +++ b/backend/src/routes/promptRouter.ts @@ -0,0 +1,18 @@ +import { Router } from "express"; +import * as PromptController from "../controllers/PromptController"; +import isAuth from "../middleware/isAuth"; + + +const promptRoutes = Router(); + +promptRoutes.get("/prompt", isAuth, PromptController.index); + +promptRoutes.post("/prompt", isAuth, PromptController.store); + +promptRoutes.get("/prompt/:promptId", isAuth, PromptController.show); + +promptRoutes.put("/prompt/:promptId", isAuth, PromptController.update); + +promptRoutes.delete("/prompt/:promptId", isAuth, PromptController.remove); + +export default promptRoutes; diff --git a/backend/src/routes/queueIntegrationRoutes.ts b/backend/src/routes/queueIntegrationRoutes.ts new file mode 100644 index 0000000..3be2ef6 --- /dev/null +++ b/backend/src/routes/queueIntegrationRoutes.ts @@ -0,0 +1,18 @@ +import { Router } from "express"; +import isAuth from "../middleware/isAuth"; + +import * as QueueIntegrationController from "../controllers/QueueIntegrationController"; + +const queueIntegrationRoutes = Router(); + +queueIntegrationRoutes.get("/queueIntegration", isAuth, QueueIntegrationController.index); + +queueIntegrationRoutes.post("/queueIntegration", isAuth, QueueIntegrationController.store); + +queueIntegrationRoutes.get("/queueIntegration/:integrationId", isAuth, QueueIntegrationController.show); + +queueIntegrationRoutes.put("/queueIntegration/:integrationId", isAuth, QueueIntegrationController.update); + +queueIntegrationRoutes.delete("/queueIntegration/:integrationId", isAuth, QueueIntegrationController.remove); + +export default queueIntegrationRoutes; \ No newline at end of file diff --git a/backend/src/routes/queueOptionRoutes.ts b/backend/src/routes/queueOptionRoutes.ts new file mode 100644 index 0000000..12a60d3 --- /dev/null +++ b/backend/src/routes/queueOptionRoutes.ts @@ -0,0 +1,34 @@ +import { Router } from "express"; +import isAuth from "../middleware/isAuth"; +import multer from "multer"; +import uploadConfig from "../config/upload"; + +const upload = multer(uploadConfig); + +import * as QueueOptionController from "../controllers/QueueOptionController"; + +const queueOptionRoutes = Router(); + +queueOptionRoutes.get("/queue-options", isAuth, QueueOptionController.index); + +queueOptionRoutes.post("/queue-options", isAuth, QueueOptionController.store); + +queueOptionRoutes.get("/queue-options/:queueOptionId", isAuth, QueueOptionController.show); + +queueOptionRoutes.put("/queue-options/:queueOptionId", isAuth, QueueOptionController.update); + +queueOptionRoutes.delete("/queue-options/:queueOptionId", isAuth, QueueOptionController.remove); + +queueOptionRoutes.post( + "/queue-options/:queueOptionId/media-upload", + isAuth, + upload.array("file"), + QueueOptionController.mediaUpload + ); + + queueOptionRoutes.delete( + "/queue-options/:queueOptionId/media-upload", + isAuth, + QueueOptionController.deleteMedia + ); +export default queueOptionRoutes; diff --git a/backend/src/routes/queueRoutes.ts b/backend/src/routes/queueRoutes.ts new file mode 100644 index 0000000..b4b31cd --- /dev/null +++ b/backend/src/routes/queueRoutes.ts @@ -0,0 +1,35 @@ +import { Router } from "express"; +import isAuth from "../middleware/isAuth"; +import multer from "multer"; +import uploadConfig from "../config/upload"; + +const upload = multer(uploadConfig); + +import * as QueueController from "../controllers/QueueController"; + +const queueRoutes = Router(); + +queueRoutes.get("/queue", isAuth, QueueController.index); + +queueRoutes.post("/queue", isAuth, QueueController.store); + +queueRoutes.get("/queue/:queueId", isAuth, QueueController.show); + +queueRoutes.put("/queue/:queueId", isAuth, QueueController.update); + +queueRoutes.delete("/queue/:queueId", isAuth, QueueController.remove); + +queueRoutes.post( + "/queue/:queueId/media-upload", + isAuth, + upload.array("file"), + QueueController.mediaUpload + ); + +queueRoutes.delete( + "/queue/:queueId/media-upload", + isAuth, + QueueController.deleteMedia + ); + +export default queueRoutes; diff --git a/backend/src/routes/quickMessageRoutes.ts b/backend/src/routes/quickMessageRoutes.ts new file mode 100644 index 0000000..d598a65 --- /dev/null +++ b/backend/src/routes/quickMessageRoutes.ts @@ -0,0 +1,37 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; + +import * as QuickMessageController from "../controllers/QuickMessageController"; +import multer from "multer"; +import uploadConfig from "../config/uploadquick"; + +const upload = multer(uploadConfig); + +const routes = express.Router(); + +routes.get("/quick-messages/list", isAuth, QuickMessageController.findList); + +routes.get("/quick-messages", isAuth, QuickMessageController.index); + +routes.get("/quick-messages/:id", isAuth, QuickMessageController.show); + +routes.post("/quick-messages", isAuth, QuickMessageController.store); + +routes.put("/quick-messages/:id", isAuth, QuickMessageController.update); + +routes.delete("/quick-messages/:id", isAuth, QuickMessageController.remove); + +routes.post( + "/quick-messages/:id/media-upload", + isAuth, + upload.array("file"), + QuickMessageController.mediaUpload + ); + + routes.delete( + "/quick-messages/:id/media-upload", + isAuth, + QuickMessageController.deleteMedia + ); + +export default routes; diff --git a/backend/src/routes/quickMessageRoutes_old.ts b/backend/src/routes/quickMessageRoutes_old.ts new file mode 100644 index 0000000..412ef1b --- /dev/null +++ b/backend/src/routes/quickMessageRoutes_old.ts @@ -0,0 +1,37 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; + +import * as QuickMessageController from "../controllers/QuickMessageController"; +import multer from "multer"; +import uploadConfig from "../config/upload"; + +const upload = multer(uploadConfig); + +const routes = express.Router(); + +routes.get("/quick-messages/list", isAuth, QuickMessageController.findList); + +routes.get("/quick-messages", isAuth, QuickMessageController.index); + +routes.get("/quick-messages/:id", isAuth, QuickMessageController.show); + +routes.post("/quick-messages", isAuth, QuickMessageController.store); + +routes.put("/quick-messages/:id", isAuth, QuickMessageController.update); + +routes.delete("/quick-messages/:id", isAuth, QuickMessageController.remove); + +routes.post( + "/quick-messages/:id/media-upload", + isAuth, + upload.array("file"), + QuickMessageController.mediaUpload + ); + + routes.delete( + "/quick-messages/:id/media-upload", + isAuth, + QuickMessageController.deleteMedia + ); + +export default routes; diff --git a/backend/src/routes/reportsRoutes.ts b/backend/src/routes/reportsRoutes.ts new file mode 100644 index 0000000..b5380a1 --- /dev/null +++ b/backend/src/routes/reportsRoutes.ts @@ -0,0 +1,21 @@ +import express from 'express'; +import isAuth from '../middleware/isAuth'; + +import * as ReportsController from '../controllers/ReportsController'; + +const reportsRoutes = express.Router(); + +reportsRoutes.get( + '/reports/appointmentsAtendent', + isAuth, + ReportsController.appointmentsAtendent, +); + +reportsRoutes.get('/reports/rushHour', isAuth, ReportsController.rushHour); +reportsRoutes.get( + '/reports/departamentRatings', + isAuth, + ReportsController.departamentRatings, +); + +export default reportsRoutes; diff --git a/backend/src/routes/scheduleRoutes.ts b/backend/src/routes/scheduleRoutes.ts new file mode 100644 index 0000000..1f9e6a6 --- /dev/null +++ b/backend/src/routes/scheduleRoutes.ts @@ -0,0 +1,26 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; + +import * as ScheduleController from "../controllers/ScheduleController"; +import multer from "multer"; +import uploadConfig from "../config/upload"; + +const upload = multer(uploadConfig); + +const scheduleRoutes = express.Router(); + +scheduleRoutes.get("/schedules", isAuth, ScheduleController.index); + +scheduleRoutes.post("/schedules", isAuth, ScheduleController.store); + +scheduleRoutes.put("/schedules/:scheduleId", isAuth, ScheduleController.update); + +scheduleRoutes.get("/schedules/:scheduleId", isAuth, ScheduleController.show); + +scheduleRoutes.delete("/schedules/:scheduleId", isAuth, ScheduleController.remove); + +scheduleRoutes.post("/schedules/:id/media-upload", isAuth, upload.array("file"), ScheduleController.mediaUpload); + +scheduleRoutes.delete("/schedules/:id/media-upload", isAuth, ScheduleController.deleteMedia); + +export default scheduleRoutes; diff --git a/backend/src/routes/settingRoutes.ts b/backend/src/routes/settingRoutes.ts new file mode 100644 index 0000000..405daca --- /dev/null +++ b/backend/src/routes/settingRoutes.ts @@ -0,0 +1,24 @@ +import { Router } from "express"; +import isAuth from "../middleware/isAuth"; + +import * as SettingController from "../controllers/SettingController"; +import multer from "multer"; +import uploadConfig from "../config/uploadlogo"; +const upload = multer(uploadConfig); + +const settingRoutes = Router(); + +settingRoutes.get("/settings", isAuth, SettingController.index); + +settingRoutes.get("/settings/:settingKey", SettingController.show); + +settingRoutes.put("/settings/:settingKey", isAuth, SettingController.update); + +settingRoutes.post( + "/settings/media-upload", + isAuth, + upload.array("file"), + SettingController.mediaUpload +); + +export default settingRoutes; diff --git a/backend/src/routes/subScriptionRoutes.ts b/backend/src/routes/subScriptionRoutes.ts new file mode 100644 index 0000000..8817b6d --- /dev/null +++ b/backend/src/routes/subScriptionRoutes.ts @@ -0,0 +1,11 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; + +import * as SubscriptionController from "../controllers/SubscriptionController"; + +const subscriptionRoutes = express.Router(); +subscriptionRoutes.post("/subscription", isAuth, SubscriptionController.createSubscription); +subscriptionRoutes.post("/subscription/create/webhook", SubscriptionController.createWebhook); +subscriptionRoutes.post("/subscription/webhook/:type?", SubscriptionController.webhook); + +export default subscriptionRoutes; diff --git a/backend/src/routes/tagRoutes.ts b/backend/src/routes/tagRoutes.ts new file mode 100644 index 0000000..6889ceb --- /dev/null +++ b/backend/src/routes/tagRoutes.ts @@ -0,0 +1,25 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; + +import * as TagController from "../controllers/TagController"; + +const tagRoutes = express.Router(); + +tagRoutes.get("/tags/list", isAuth, TagController.list); + +tagRoutes.get("/tags", isAuth, TagController.index); + +tagRoutes.get("/tags/kanban", isAuth, TagController.kanban); + +tagRoutes.post("/tags", isAuth, TagController.store); + +tagRoutes.put("/tags/:tagId", isAuth, TagController.update); + +tagRoutes.get("/tags/:tagId", isAuth, TagController.show); + +tagRoutes.delete("/tags/:tagId", isAuth, TagController.remove); + +tagRoutes.post("/tags/sync", isAuth, TagController.syncTags); + + +export default tagRoutes; diff --git a/backend/src/routes/ticketNoteRoutes.ts b/backend/src/routes/ticketNoteRoutes.ts new file mode 100644 index 0000000..88462bb --- /dev/null +++ b/backend/src/routes/ticketNoteRoutes.ts @@ -0,0 +1,28 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; + +import * as TicketNoteController from "../controllers/TicketNoteController"; + +const ticketNoteRoutes = express.Router(); + +ticketNoteRoutes.get( + "/ticket-notes/list", + isAuth, + TicketNoteController.findFilteredList +); + +ticketNoteRoutes.get("/ticket-notes", isAuth, TicketNoteController.index); + +ticketNoteRoutes.get("/ticket-notes/:id", isAuth, TicketNoteController.show); + +ticketNoteRoutes.post("/ticket-notes", isAuth, TicketNoteController.store); + +ticketNoteRoutes.put("/ticket-notes/:id", isAuth, TicketNoteController.update); + +ticketNoteRoutes.delete( + "/ticket-notes/:id", + isAuth, + TicketNoteController.remove +); + +export default ticketNoteRoutes; diff --git a/backend/src/routes/ticketRoutes.ts b/backend/src/routes/ticketRoutes.ts new file mode 100644 index 0000000..9fa67e6 --- /dev/null +++ b/backend/src/routes/ticketRoutes.ts @@ -0,0 +1,26 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; + +import * as TicketController from "../controllers/TicketController"; + +const ticketRoutes = express.Router(); + +ticketRoutes.get("/tickets", isAuth, TicketController.index); + +ticketRoutes.get("/ticket/reports", isAuth, TicketController.report); + +ticketRoutes.get("/tickets/:ticketId", isAuth, TicketController.show); + +ticketRoutes.get("/ticket/kanban", isAuth, TicketController.kanban); + +ticketRoutes.get("/tickets/u/:uuid", isAuth, TicketController.showFromUUID); + +ticketRoutes.post("/tickets", isAuth, TicketController.store); + +ticketRoutes.put("/tickets/:ticketId", isAuth, TicketController.update); + +ticketRoutes.delete("/tickets/:ticketId", isAuth, TicketController.remove); + +ticketRoutes.post("/tickets/closeAll", isAuth, TicketController.closeAll); + +export default ticketRoutes; diff --git a/backend/src/routes/ticketTagRoutes.ts b/backend/src/routes/ticketTagRoutes.ts new file mode 100644 index 0000000..759f203 --- /dev/null +++ b/backend/src/routes/ticketTagRoutes.ts @@ -0,0 +1,11 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; + +import * as TicketTagController from "../controllers/TicketTagController"; + +const ticketTagRoutes = express.Router(); + +ticketTagRoutes.put("/ticket-tags/:ticketId/:tagId", isAuth, TicketTagController.store); +ticketTagRoutes.delete("/ticket-tags/:ticketId", isAuth, TicketTagController.remove); + +export default ticketTagRoutes; diff --git a/backend/src/routes/userRoutes.ts b/backend/src/routes/userRoutes.ts new file mode 100644 index 0000000..4fbf2c1 --- /dev/null +++ b/backend/src/routes/userRoutes.ts @@ -0,0 +1,20 @@ +import { Router } from "express"; + +import isAuth from "../middleware/isAuth"; +import * as UserController from "../controllers/UserController"; + +const userRoutes = Router(); + +userRoutes.get("/users", isAuth, UserController.index); + +userRoutes.get("/users/list", isAuth, UserController.list); + +userRoutes.post("/users", isAuth, UserController.store); + +userRoutes.put("/users/:userId", isAuth, UserController.update); + +userRoutes.get("/users/:userId", isAuth, UserController.show); + +userRoutes.delete("/users/:userId", isAuth, UserController.remove); + +export default userRoutes; diff --git a/backend/src/routes/versionRoutes.ts b/backend/src/routes/versionRoutes.ts new file mode 100644 index 0000000..9ff2cbe --- /dev/null +++ b/backend/src/routes/versionRoutes.ts @@ -0,0 +1,9 @@ +import { Router } from "express"; + +import * as VerssionController from "../controllers/VersionController"; + +const versionRouter = Router(); + +versionRouter.get("/version", VerssionController.index); + +export default versionRouter; diff --git a/backend/src/routes/whatsappRoutes.ts b/backend/src/routes/whatsappRoutes.ts new file mode 100644 index 0000000..22fb12a --- /dev/null +++ b/backend/src/routes/whatsappRoutes.ts @@ -0,0 +1,24 @@ +import express from "express"; +import isAuth from "../middleware/isAuth"; + +import * as WhatsAppController from "../controllers/WhatsAppController"; + +const whatsappRoutes = express.Router(); + +whatsappRoutes.get("/whatsapp/", isAuth, WhatsAppController.index); + +whatsappRoutes.post("/whatsapp/", isAuth, WhatsAppController.store); + +whatsappRoutes.get("/whatsapp/:whatsappId", isAuth, WhatsAppController.show); + +whatsappRoutes.put("/whatsapp/:whatsappId", isAuth, WhatsAppController.update); + +whatsappRoutes.post("/whatsapp-restart/", isAuth, WhatsAppController.restart); + +whatsappRoutes.delete( + "/whatsapp/:whatsappId", + isAuth, + WhatsAppController.remove +); + +export default whatsappRoutes; diff --git a/backend/src/routes/whatsappSessionRoutes.ts b/backend/src/routes/whatsappSessionRoutes.ts new file mode 100644 index 0000000..731d847 --- /dev/null +++ b/backend/src/routes/whatsappSessionRoutes.ts @@ -0,0 +1,26 @@ +import { Router } from "express"; +import isAuth from "../middleware/isAuth"; + +import WhatsAppSessionController from "../controllers/WhatsAppSessionController"; + +const whatsappSessionRoutes = Router(); + +whatsappSessionRoutes.post( + "/whatsappsession/:whatsappId", + isAuth, + WhatsAppSessionController.store +); + +whatsappSessionRoutes.put( + "/whatsappsession/:whatsappId", + isAuth, + WhatsAppSessionController.update +); + +whatsappSessionRoutes.delete( + "/whatsappsession/:whatsappId", + isAuth, + WhatsAppSessionController.remove +); + +export default whatsappSessionRoutes; diff --git a/backend/src/server.ts b/backend/src/server.ts new file mode 100644 index 0000000..4fcc864 --- /dev/null +++ b/backend/src/server.ts @@ -0,0 +1,67 @@ +import gracefulShutdown from "http-graceful-shutdown"; +import app from "./app"; +import { initIO } from "./libs/socket"; +import { logger } from "./utils/logger"; +import { StartAllWhatsAppsSessions } from "./services/WbotServices/StartAllWhatsAppsSessions"; +import Company from "./models/Company"; +import { startQueueProcess } from "./queues"; +import { TransferTicketQueue } from "./wbotTransferTicketQueue"; +import cron from "node-cron"; + +const server = app.listen(process.env.PORT, async () => { + try { + const companies = await Company.findAll(); + const sessionPromises = []; + + for (const c of companies) { + sessionPromises.push(StartAllWhatsAppsSessions(c.id)); + } + + await Promise.all(sessionPromises); + startQueueProcess(); + logger.info(`Server started on port: ${process.env.PORT}`); + } catch (error) { + logger.error("Error starting server:", error); + process.exit(1); + } +}); + +process.on("uncaughtException", err => { + console.error(`${new Date().toUTCString()} uncaughtException:`, err.message); + console.error(err.stack); + process.exit(1); +}); + +process.on("unhandledRejection", (reason, p) => { + console.error( + `${new Date().toUTCString()} unhandledRejection:`, + reason, + p + ); + process.exit(1); +}); + + +cron.schedule("* * * * *", async () => { + try { + logger.info(`Serviço de transferência de tickets iniciado`); + await TransferTicketQueue(); + } catch (error) { + logger.error("Error in cron job:", error); + } +}); + +initIO(server); + +// Configure graceful shutdown to handle all outstanding promises +gracefulShutdown(server, { + signals: "SIGINT SIGTERM", + timeout: 30000, // 30 seconds + onShutdown: async () => { + logger.info("Gracefully shutting down..."); + // Add any other cleanup code here, if necessary + }, + finally: () => { + logger.info("Server shutdown complete."); + } +}); diff --git a/backend/src/services/AnnouncementService/CreateService.ts b/backend/src/services/AnnouncementService/CreateService.ts new file mode 100644 index 0000000..0a81193 --- /dev/null +++ b/backend/src/services/AnnouncementService/CreateService.ts @@ -0,0 +1,32 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import Announcement from "../../models/Announcement"; + +interface Data { + priority: string; + title: string; + text: string; + status: string; + companyId: number; +} + +const CreateService = async (data: Data): Promise => { + const { title, text } = data; + + const ticketnoteSchema = Yup.object().shape({ + title: Yup.string().required("ERR_ANNOUNCEMENT_REQUIRED"), + text: Yup.string().required("ERR_ANNOUNCEMENT_REQUIRED") + }); + + try { + await ticketnoteSchema.validate({ title, text }); + } catch (err: any) { + throw new AppError(err.message); + } + + const record = await Announcement.create(data); + + return record; +}; + +export default CreateService; diff --git a/backend/src/services/AnnouncementService/DeleteService.ts b/backend/src/services/AnnouncementService/DeleteService.ts new file mode 100644 index 0000000..c3aee30 --- /dev/null +++ b/backend/src/services/AnnouncementService/DeleteService.ts @@ -0,0 +1,16 @@ +import Announcement from "../../models/Announcement"; +import AppError from "../../errors/AppError"; + +const DeleteService = async (id: string): Promise => { + const record = await Announcement.findOne({ + where: { id } + }); + + if (!record) { + throw new AppError("ERR_NO_ANNOUNCEMENT_FOUND", 404); + } + + await record.destroy(); +}; + +export default DeleteService; diff --git a/backend/src/services/AnnouncementService/FindAllService.ts b/backend/src/services/AnnouncementService/FindAllService.ts new file mode 100644 index 0000000..13209f7 --- /dev/null +++ b/backend/src/services/AnnouncementService/FindAllService.ts @@ -0,0 +1,10 @@ +import Announcement from "../../models/Announcement"; + +const FindAllService = async (): Promise => { + const records: Announcement[] = await Announcement.findAll({ + order: [["createdAt", "DESC"]] + }); + return records; +}; + +export default FindAllService; diff --git a/backend/src/services/AnnouncementService/FindService.ts b/backend/src/services/AnnouncementService/FindService.ts new file mode 100644 index 0000000..5125672 --- /dev/null +++ b/backend/src/services/AnnouncementService/FindService.ts @@ -0,0 +1,20 @@ +import Announcement from "../../models/Announcement"; +import Company from "../../models/Company"; + +type Params = { + companyId: string; +}; + +const FindService = async ({ companyId }: Params): Promise => { + const notes: Announcement[] = await Announcement.findAll({ + where: { + companyId + }, + include: [{ model: Company, as: "company", attributes: ["id", "name"] }], + order: [["createdAt", "DESC"]] + }); + + return notes; +}; + +export default FindService; diff --git a/backend/src/services/AnnouncementService/ListService.ts b/backend/src/services/AnnouncementService/ListService.ts new file mode 100644 index 0000000..474a761 --- /dev/null +++ b/backend/src/services/AnnouncementService/ListService.ts @@ -0,0 +1,58 @@ +import { Op, fn, col, where } from "sequelize"; +import { isEmpty } from "lodash"; +import Announcement from "../../models/Announcement"; + +interface Request { + searchParam?: string; + pageNumber?: string; +} + +interface Response { + records: Announcement[]; + count: number; + hasMore: boolean; +} + +const ListService = async ({ + searchParam = "", + pageNumber = "1" +}: Request): Promise => { + let whereCondition: any = { + status: true + }; + + if (!isEmpty(searchParam)) { + whereCondition = { + ...whereCondition, + [Op.or]: [ + { + title: where( + fn("LOWER", col("Announcement.title")), + "LIKE", + `%${searchParam.toLowerCase().trim()}%` + ) + } + ] + }; + } + + const limit = 20; + const offset = limit * (+pageNumber - 1); + + const { count, rows: records } = await Announcement.findAndCountAll({ + where: whereCondition, + limit, + offset, + order: [["createdAt", "DESC"]] + }); + + const hasMore = count > offset + records.length; + + return { + records, + count, + hasMore + }; +}; + +export default ListService; diff --git a/backend/src/services/AnnouncementService/ShowService.ts b/backend/src/services/AnnouncementService/ShowService.ts new file mode 100644 index 0000000..d00e28f --- /dev/null +++ b/backend/src/services/AnnouncementService/ShowService.ts @@ -0,0 +1,14 @@ +import Announcement from "../../models/Announcement"; +import AppError from "../../errors/AppError"; + +const ShowService = async (id: string | number): Promise => { + const record = await Announcement.findByPk(id); + + if (!record) { + throw new AppError("ERR_NO_ANNOUNCEMENT_FOUND", 404); + } + + return record; +}; + +export default ShowService; diff --git a/backend/src/services/AnnouncementService/UpdateService.ts b/backend/src/services/AnnouncementService/UpdateService.ts new file mode 100644 index 0000000..7389cee --- /dev/null +++ b/backend/src/services/AnnouncementService/UpdateService.ts @@ -0,0 +1,27 @@ +import AppError from "../../errors/AppError"; +import Announcement from "../../models/Announcement"; + +interface Data { + id: number | string; + priority: string; + title: string; + text: string; + status: string; + companyId: number; +} + +const UpdateService = async (data: Data): Promise => { + const { id } = data; + + const record = await Announcement.findByPk(id); + + if (!record) { + throw new AppError("ERR_NO_ANNOUNCEMENT_FOUND", 404); + } + + await record.update(data); + + return record; +}; + +export default UpdateService; diff --git a/backend/src/services/AuthServices/FindUserFromToken.ts b/backend/src/services/AuthServices/FindUserFromToken.ts new file mode 100644 index 0000000..20d57f4 --- /dev/null +++ b/backend/src/services/AuthServices/FindUserFromToken.ts @@ -0,0 +1,18 @@ +import { verify } from "jsonwebtoken"; +import ShowUserService from "../UserServices/ShowUserService"; +import authConfig from "../../config/auth"; +import User from "../../models/User"; + +interface RefreshTokenPayload { + id: string; + tokenVersion: number; + companyId: number; +} + +export default async function FindUserFromToken(token: string): Promise { + const decoded = verify(token, authConfig.refreshSecret); + const { id } = decoded as RefreshTokenPayload; + + const user = await ShowUserService(id); + return user; +} diff --git a/backend/src/services/AuthServices/RefreshTokenService.ts b/backend/src/services/AuthServices/RefreshTokenService.ts new file mode 100644 index 0000000..fb19102 --- /dev/null +++ b/backend/src/services/AuthServices/RefreshTokenService.ts @@ -0,0 +1,48 @@ +import { verify } from "jsonwebtoken"; +import { Response as Res } from "express"; + +import User from "../../models/User"; +import AppError from "../../errors/AppError"; +import ShowUserService from "../UserServices/ShowUserService"; +import authConfig from "../../config/auth"; +import { + createAccessToken, + createRefreshToken +} from "../../helpers/CreateTokens"; + +interface RefreshTokenPayload { + id: string; + tokenVersion: number; + companyId: number; +} + +interface Response { + user: User; + newToken: string; + refreshToken: string; +} + +export const RefreshTokenService = async ( + res: Res, + token: string +): Promise => { + try { + const decoded = verify(token, authConfig.refreshSecret); + const { id, tokenVersion, companyId } = decoded as RefreshTokenPayload; + + const user = await ShowUserService(id); + + if (user.tokenVersion !== tokenVersion) { + res.clearCookie("jrt"); + throw new AppError("ERR_SESSION_EXPIRED", 401); + } + + const newToken = createAccessToken(user); + const refreshToken = createRefreshToken(user); + + return { user, newToken, refreshToken }; + } catch (err) { + res.clearCookie("jrt"); + throw new AppError("ERR_SESSION_EXPIRED", 401); + } +}; diff --git a/backend/src/services/BaileysChatServices/CreateOrUpdateBaileysChatService.ts b/backend/src/services/BaileysChatServices/CreateOrUpdateBaileysChatService.ts new file mode 100644 index 0000000..37e5818 --- /dev/null +++ b/backend/src/services/BaileysChatServices/CreateOrUpdateBaileysChatService.ts @@ -0,0 +1,39 @@ +import { Chat } from "@whiskeysockets/baileys"; +import BaileysChats from "../../models/BaileysChats"; + +export const CreateOrUpdateBaileysChatService = async ( + whatsappId: number, + chat: Partial, +): Promise => { + const { id, conversationTimestamp, unreadCount } = chat; + const baileysChat = await BaileysChats.findOne({ + where: { + whatsappId, + jid: id, + } + }); + + if (baileysChat) { + const baileysChats = await baileysChat.update({ + conversationTimestamp, + unreadCount: unreadCount ? baileysChat.unreadCount + unreadCount : 0 + }); + + return baileysChats; + } + // timestamp now + + const timestamp = new Date().getTime(); + + // convert timestamp to number + const conversationTimestampNumber = Number(timestamp); + + const baileysChats = await BaileysChats.create({ + whatsappId, + jid: id, + conversationTimestamp: conversationTimestamp || conversationTimestampNumber, + unreadCount: unreadCount || 1, + }); + + return baileysChats; +}; diff --git a/backend/src/services/BaileysChatServices/DeleteBaileysChatServices.ts b/backend/src/services/BaileysChatServices/DeleteBaileysChatServices.ts new file mode 100644 index 0000000..57313ff --- /dev/null +++ b/backend/src/services/BaileysChatServices/DeleteBaileysChatServices.ts @@ -0,0 +1,13 @@ +import { ShowBaileysChatService } from "./ShowBaileysChatService"; + +export const DeleteBaileysChatServices = async ( + whatsappId: number, + jid: string, +): Promise => { + const showBaileysChatService = await ShowBaileysChatService( + whatsappId, + jid, + ); + + showBaileysChatService.destroy(); +}; diff --git a/backend/src/services/BaileysChatServices/ShowBaileysChatService.ts b/backend/src/services/BaileysChatServices/ShowBaileysChatService.ts new file mode 100644 index 0000000..a93ca2d --- /dev/null +++ b/backend/src/services/BaileysChatServices/ShowBaileysChatService.ts @@ -0,0 +1,19 @@ +import AppError from "../../errors/AppError"; +import BaileysChats from "../../models/BaileysChats"; + +export const ShowBaileysChatService = async ( + whatsappId: number, + jid: string, +): Promise => { + const baileysChat = await BaileysChats.findOne({ + where: { + whatsappId, + jid, + } + }); + + if (baileysChat) { + return baileysChat; + } + +}; diff --git a/backend/src/services/BaileysChatServices/UpdateBaileysChatServices.ts b/backend/src/services/BaileysChatServices/UpdateBaileysChatServices.ts new file mode 100644 index 0000000..dd4a304 --- /dev/null +++ b/backend/src/services/BaileysChatServices/UpdateBaileysChatServices.ts @@ -0,0 +1,30 @@ +import AppError from "../../errors/AppError"; +import BaileysChats from "../../models/BaileysChats"; + +interface Data { + id?: string; + conversationTimestamp?: number; + unreadCount?: number; +} + +export const UpdateBaileysChatServices = async ( + whatsappId: number, + jid: string, + data: Data +): Promise => { + const baileysChat = await BaileysChats.findOne({ + where: { + whatsappId, + jid + } + }); + + if (baileysChat) { + await baileysChat.update({ + conversationTimestamp: data.conversationTimestamp, + unreadCount: data.unreadCount + }); + + return baileysChat; + } +}; diff --git a/backend/src/services/BaileysServices/CreateOrUpdateBaileysService.ts b/backend/src/services/BaileysServices/CreateOrUpdateBaileysService.ts new file mode 100644 index 0000000..864cc50 --- /dev/null +++ b/backend/src/services/BaileysServices/CreateOrUpdateBaileysService.ts @@ -0,0 +1,53 @@ +import { Chat, Contact } from "@whiskeysockets/baileys"; +import { isArray } from "lodash"; +import Baileys from "../../models/Baileys"; + +interface Request { + whatsappId: number; + contacts?: Contact[]; + chats?: Chat[]; +} + +const createOrUpdateBaileysService = async ({ + whatsappId, + contacts +}: Request): Promise => { + const baileysExists = await Baileys.findOne({ + where: { whatsappId } + }); + + if (!contacts) { + return baileysExists; + } + + if (baileysExists) { + const getContacts = []; + + const baileysContacts = baileysExists.contacts + ? JSON.parse(baileysExists.contacts) + : []; + + if (isArray(baileysContacts)) { + getContacts.push(...baileysContacts); + } + + getContacts.push(...contacts); + getContacts.sort(); + getContacts.filter((v, i, a) => a.indexOf(v) === i); + + const newBaileys = await baileysExists.update({ + contacts: JSON.stringify(getContacts) + }); + + return newBaileys; + } + + const baileys = await Baileys.create({ + whatsappId, + contacts: JSON.stringify(contacts) + }); + + return baileys; +}; + +export default createOrUpdateBaileysService; \ No newline at end of file diff --git a/backend/src/services/BaileysServices/DeleteBaileysService.ts b/backend/src/services/BaileysServices/DeleteBaileysService.ts new file mode 100644 index 0000000..12396ba --- /dev/null +++ b/backend/src/services/BaileysServices/DeleteBaileysService.ts @@ -0,0 +1,15 @@ +import Baileys from "../../models/Baileys"; + +const DeleteBaileysService = async (id: string | number): Promise => { + const baileysData = await Baileys.findOne({ + where: { + whatsappId: id + } + }); + + if (baileysData) { + await baileysData.destroy(); + } +}; + +export default DeleteBaileysService; diff --git a/backend/src/services/BaileysServices/ShowBaileysService.ts b/backend/src/services/BaileysServices/ShowBaileysService.ts new file mode 100644 index 0000000..5c3d5fb --- /dev/null +++ b/backend/src/services/BaileysServices/ShowBaileysService.ts @@ -0,0 +1,18 @@ +import Baileys from "../../models/Baileys"; +import AppError from "../../errors/AppError"; + +const ShowBaileysService = async (id: string | number): Promise => { + const baileysData = await Baileys.findOne({ + where: { + whatsappId: id + } + }); + + if (!baileysData) { + throw new AppError("ERR_NO_BAILEYS_DATA_FOUND", 404); + } + + return baileysData; +}; + +export default ShowBaileysService; diff --git a/backend/src/services/CampaignService/CancelService.ts b/backend/src/services/CampaignService/CancelService.ts new file mode 100644 index 0000000..2c83668 --- /dev/null +++ b/backend/src/services/CampaignService/CancelService.ts @@ -0,0 +1,26 @@ +import { Op } from "sequelize"; +import Campaign from "../../models/Campaign"; +import CampaignShipping from "../../models/CampaignShipping"; +import { campaignQueue } from "../../queues"; + +export async function CancelService(id: number) { + const campaign = await Campaign.findByPk(id); + await campaign.update({ status: "CANCELADA" }); + + const recordsToCancel = await CampaignShipping.findAll({ + where: { + campaignId: campaign.id, + jobId: { [Op.not]: null }, + deliveredAt: null + } + }); + + const promises = []; + + for (let record of recordsToCancel) { + const job = await campaignQueue.getJob(+record.jobId); + promises.push(job.remove()); + } + + await Promise.all(promises); +} diff --git a/backend/src/services/CampaignService/CreateService.ts b/backend/src/services/CampaignService/CreateService.ts new file mode 100644 index 0000000..a50db6d --- /dev/null +++ b/backend/src/services/CampaignService/CreateService.ts @@ -0,0 +1,58 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import Campaign from "../../models/Campaign"; +import ContactList from "../../models/ContactList"; +import Whatsapp from "../../models/Whatsapp"; + +interface Data { + name: string; + status: string; + confirmation: boolean; + scheduledAt: string; + companyId: number; + contactListId: number; + message1?: string; + message2?: string; + message3?: string; + message4?: string; + message5?: string; + confirmationMessage1?: string; + confirmationMessage2?: string; + confirmationMessage3?: string; + confirmationMessage4?: string; + confirmationMessage5?: string; + fileListId: number; +} + +const CreateService = async (data: Data): Promise => { + const { name } = data; + + const ticketnoteSchema = Yup.object().shape({ + name: Yup.string() + .min(3, "ERR_CAMPAIGN_INVALID_NAME") + .required("ERR_CAMPAIGN_REQUIRED") + }); + + try { + await ticketnoteSchema.validate({ name }); + } catch (err: any) { + throw new AppError(err.message); + } + + if (data.scheduledAt != null && data.scheduledAt != "") { + data.status = "PROGRAMADA"; + } + + const record = await Campaign.create(data); + + await record.reload({ + include: [ + { model: ContactList }, + { model: Whatsapp, attributes: ["id", "name"] } + ] + }); + + return record; +}; + +export default CreateService; diff --git a/backend/src/services/CampaignService/DeleteService.ts b/backend/src/services/CampaignService/DeleteService.ts new file mode 100644 index 0000000..4038555 --- /dev/null +++ b/backend/src/services/CampaignService/DeleteService.ts @@ -0,0 +1,20 @@ +import Campaign from "../../models/Campaign"; +import AppError from "../../errors/AppError"; + +const DeleteService = async (id: string): Promise => { + const record = await Campaign.findOne({ + where: { id } + }); + + if (!record) { + throw new AppError("ERR_NO_CAMPAIGN_FOUND", 404); + } + + if (record.status === "EM_ANDAMENTO") { + throw new AppError("Não é permitido excluir campanha em andamento", 400); + } + + await record.destroy(); +}; + +export default DeleteService; diff --git a/backend/src/services/CampaignService/FindAllService.ts b/backend/src/services/CampaignService/FindAllService.ts new file mode 100644 index 0000000..cff8b37 --- /dev/null +++ b/backend/src/services/CampaignService/FindAllService.ts @@ -0,0 +1,10 @@ +import Campaign from "../../models/Campaign"; + +const FindAllService = async (): Promise => { + const records: Campaign[] = await Campaign.findAll({ + order: [["name", "ASC"]] + }); + return records; +}; + +export default FindAllService; diff --git a/backend/src/services/CampaignService/FindService.ts b/backend/src/services/CampaignService/FindService.ts new file mode 100644 index 0000000..128e4c1 --- /dev/null +++ b/backend/src/services/CampaignService/FindService.ts @@ -0,0 +1,20 @@ +import Campaign from "../../models/Campaign"; +import Company from "../../models/Company"; + +type Params = { + companyId: string; +}; + +const FindService = async ({ companyId }: Params): Promise => { + const notes: Campaign[] = await Campaign.findAll({ + where: { + companyId + }, + include: [{ model: Company, as: "company", attributes: ["id", "name"] }], + order: [["name", "ASC"]] + }); + + return notes; +}; + +export default FindService; diff --git a/backend/src/services/CampaignService/ListService.ts b/backend/src/services/CampaignService/ListService.ts new file mode 100644 index 0000000..234504e --- /dev/null +++ b/backend/src/services/CampaignService/ListService.ts @@ -0,0 +1,66 @@ +import { Op, fn, col, where } from "sequelize"; +import Campaign from "../../models/Campaign"; +import { isEmpty } from "lodash"; +import ContactList from "../../models/ContactList"; +import Whatsapp from "../../models/Whatsapp"; + +interface Request { + companyId: number | string; + searchParam?: string; + pageNumber?: string; +} + +interface Response { + records: Campaign[]; + count: number; + hasMore: boolean; +} + +const ListService = async ({ + searchParam = "", + pageNumber = "1", + companyId +}: Request): Promise => { + let whereCondition: any = { + companyId + }; + + if (!isEmpty(searchParam)) { + whereCondition = { + ...whereCondition, + [Op.or]: [ + { + name: where( + fn("LOWER", col("Campaign.name")), + "LIKE", + `%${searchParam.toLowerCase().trim()}%` + ) + } + ] + }; + } + + const limit = 20; + const offset = limit * (+pageNumber - 1); + + const { count, rows: records } = await Campaign.findAndCountAll({ + where: whereCondition, + limit, + offset, + order: [["name", "ASC"]], + include: [ + { model: ContactList }, + { model: Whatsapp, attributes: ["id", "name"] } + ] + }); + + const hasMore = count > offset + records.length; + + return { + records, + count, + hasMore + }; +}; + +export default ListService; diff --git a/backend/src/services/CampaignService/RestartService.ts b/backend/src/services/CampaignService/RestartService.ts new file mode 100644 index 0000000..3ec214d --- /dev/null +++ b/backend/src/services/CampaignService/RestartService.ts @@ -0,0 +1,12 @@ +import Campaign from "../../models/Campaign"; +import { campaignQueue } from "../../queues"; + +export async function RestartService(id: number) { + const campaign = await Campaign.findByPk(id); + await campaign.update({ status: "EM_ANDAMENTO" }); + + await campaignQueue.add("ProcessCampaign", { + id: campaign.id, + delay: 3000 + }); +} diff --git a/backend/src/services/CampaignService/ShowService.ts b/backend/src/services/CampaignService/ShowService.ts new file mode 100644 index 0000000..16974a5 --- /dev/null +++ b/backend/src/services/CampaignService/ShowService.ts @@ -0,0 +1,24 @@ +import Campaign from "../../models/Campaign"; +import AppError from "../../errors/AppError"; +import CampaignShipping from "../../models/CampaignShipping"; +import ContactList from "../../models/ContactList"; +import ContactListItem from "../../models/ContactListItem"; +import Whatsapp from "../../models/Whatsapp"; + +const ShowService = async (id: string | number): Promise => { + const record = await Campaign.findByPk(id, { + include: [ + { model: CampaignShipping }, + { model: ContactList, include: [{ model: ContactListItem }] }, + { model: Whatsapp, attributes: ["id", "name"] } + ] + }); + + if (!record) { + throw new AppError("ERR_NO_TICKETNOTE_FOUND", 404); + } + + return record; +}; + +export default ShowService; diff --git a/backend/src/services/CampaignService/UpdateService.ts b/backend/src/services/CampaignService/UpdateService.ts new file mode 100644 index 0000000..fa33ed4 --- /dev/null +++ b/backend/src/services/CampaignService/UpdateService.ts @@ -0,0 +1,63 @@ +import AppError from "../../errors/AppError"; +import Campaign from "../../models/Campaign"; +import ContactList from "../../models/ContactList"; +import Whatsapp from "../../models/Whatsapp"; + +interface Data { + id: number | string; + name: string; + status: string; + confirmation: boolean; + scheduledAt: string; + companyId: number; + contactListId: number; + message1?: string; + message2?: string; + message3?: string; + message4?: string; + message5?: string; + confirmationMessage1?: string; + confirmationMessage2?: string; + confirmationMessage3?: string; + confirmationMessage4?: string; + confirmationMessage5?: string; + fileListId: number; +} + +const UpdateService = async (data: Data): Promise => { + const { id } = data; + + const record = await Campaign.findByPk(id); + + if (!record) { + throw new AppError("ERR_NO_CAMPAIGN_FOUND", 404); + } + + if (["INATIVA", "PROGRAMADA", "CANCELADA"].indexOf(data.status) === -1) { + throw new AppError( + "Só é permitido alterar campanha Inativa e Programada", + 400 + ); + } + + if ( + data.scheduledAt != null && + data.scheduledAt != "" && + data.status === "INATIVA" + ) { + data.status = "PROGRAMADA"; + } + + await record.update(data); + + await record.reload({ + include: [ + { model: ContactList }, + { model: Whatsapp, attributes: ["id", "name"] } + ] + }); + + return record; +}; + +export default UpdateService; diff --git a/backend/src/services/CampaignSettingServices/CreateService.ts b/backend/src/services/CampaignSettingServices/CreateService.ts new file mode 100644 index 0000000..7afeee4 --- /dev/null +++ b/backend/src/services/CampaignSettingServices/CreateService.ts @@ -0,0 +1,36 @@ +import CampaignSetting from "../../models/CampaignSetting"; +import { isArray, isObject } from "lodash"; + +interface Data { + settings: any; +} + +const CreateService = async ( + data: Data, + companyId: number +): Promise => { + const settings = []; + for (let settingKey of Object.keys(data.settings)) { + const value = + isArray(data.settings[settingKey]) || isObject(data.settings[settingKey]) + ? JSON.stringify(data.settings[settingKey]) + : data.settings[settingKey]; + const [record, created] = await CampaignSetting.findOrCreate({ + where: { + key: settingKey, + companyId + }, + defaults: { key: settingKey, value, companyId } + }); + + if (!created) { + await record.update({ value }); + } + + settings.push(record); + } + + return settings; +}; + +export default CreateService; diff --git a/backend/src/services/CampaignSettingServices/ListService.ts b/backend/src/services/CampaignSettingServices/ListService.ts new file mode 100644 index 0000000..009df3a --- /dev/null +++ b/backend/src/services/CampaignSettingServices/ListService.ts @@ -0,0 +1,34 @@ +import { Op, fn, col, where } from "sequelize"; +import Campaign from "../../models/Campaign"; +import { isEmpty } from "lodash"; +import ContactList from "../../models/ContactList"; +import Whatsapp from "../../models/Whatsapp"; +import CampaignSetting from "../../models/CampaignSetting"; + +interface Request { + companyId: number | string; + searchParam?: string; + pageNumber?: string; +} + +interface Response { + records: Campaign[]; + count: number; + hasMore: boolean; +} + +const ListService = async ({ + companyId +}: Request): Promise => { + let whereCondition: any = { + companyId + }; + + const records = await CampaignSetting.findAll({ + where: whereCondition + }); + + return records; +}; + +export default ListService; diff --git a/backend/src/services/ChatService/CreateMessageService.ts b/backend/src/services/ChatService/CreateMessageService.ts new file mode 100644 index 0000000..946e615 --- /dev/null +++ b/backend/src/services/ChatService/CreateMessageService.ts @@ -0,0 +1,52 @@ +import { Op } from "sequelize"; +import Chat from "../../models/Chat"; +import ChatMessage from "../../models/ChatMessage"; +import ChatUser from "../../models/ChatUser"; +import User from "../../models/User"; + +export interface ChatMessageData { + senderId: number; + chatId: number; + message: string; +} + +export default async function CreateMessageService({ + senderId, + chatId, + message +}: ChatMessageData) { + const newMessage = await ChatMessage.create({ + senderId, + chatId, + message + }); + + await newMessage.reload({ + include: [ + { model: User, as: "sender", attributes: ["id", "name"] }, + { + model: Chat, + as: "chat", + include: [{ model: ChatUser, as: "users" }] + } + ] + }); + + const sender = await User.findByPk(senderId); + + await newMessage.chat.update({ lastMessage: `${sender.name}: ${message}` }); + + const chatUsers = await ChatUser.findAll({ + where: { chatId } + }); + + for (let chatUser of chatUsers) { + if (chatUser.userId === senderId) { + await chatUser.update({ unreads: 0 }); + } else { + await chatUser.update({ unreads: chatUser.unreads + 1 }); + } + } + + return newMessage; +} diff --git a/backend/src/services/ChatService/CreateService.ts b/backend/src/services/ChatService/CreateService.ts new file mode 100644 index 0000000..6b1ff9e --- /dev/null +++ b/backend/src/services/ChatService/CreateService.ts @@ -0,0 +1,38 @@ +import Chat from "../../models/Chat"; +import ChatUser from "../../models/ChatUser"; +import User from "../../models/User"; + +interface Data { + ownerId: number; + companyId: number; + users: any[]; + title: string; +} + +const CreateService = async (data: Data): Promise => { + const { ownerId, companyId, users, title } = data; + + const record = await Chat.create({ + ownerId, + companyId, + title + }); + + if (Array.isArray(users) && users.length > 0) { + await ChatUser.create({ chatId: record.id, userId: ownerId }); + for (let user of users) { + await ChatUser.create({ chatId: record.id, userId: user.id }); + } + } + + await record.reload({ + include: [ + { model: ChatUser, as: "users", include: [{ model: User, as: "user" }] }, + { model: User, as: "owner" } + ] + }); + + return record; +}; + +export default CreateService; diff --git a/backend/src/services/ChatService/DeleteService.ts b/backend/src/services/ChatService/DeleteService.ts new file mode 100644 index 0000000..e560f24 --- /dev/null +++ b/backend/src/services/ChatService/DeleteService.ts @@ -0,0 +1,16 @@ +import Chat from "../../models/Chat"; +import AppError from "../../errors/AppError"; + +const DeleteService = async (id: string): Promise => { + const record = await Chat.findOne({ + where: { id } + }); + + if (!record) { + throw new AppError("ERR_NO_CHAT_FOUND", 404); + } + + await record.destroy(); +}; + +export default DeleteService; diff --git a/backend/src/services/ChatService/FindAllService.ts b/backend/src/services/ChatService/FindAllService.ts new file mode 100644 index 0000000..afbc09a --- /dev/null +++ b/backend/src/services/ChatService/FindAllService.ts @@ -0,0 +1,10 @@ +import Chat from "../../models/Chat"; + +const FindAllService = async (): Promise => { + const records: Chat[] = await Chat.findAll({ + order: [["createdAt", "DESC"]] + }); + return records; +}; + +export default FindAllService; diff --git a/backend/src/services/ChatService/FindMessages.ts b/backend/src/services/ChatService/FindMessages.ts new file mode 100644 index 0000000..f2dd5f4 --- /dev/null +++ b/backend/src/services/ChatService/FindMessages.ts @@ -0,0 +1,58 @@ +import AppError from "../../errors/AppError"; +import ChatMessage from "../../models/ChatMessage"; +import ChatUser from "../../models/ChatUser"; +import User from "../../models/User"; + +import { sortBy } from "lodash"; + +interface Request { + chatId: string; + ownerId: number; + pageNumber?: string; +} + +interface Response { + records: ChatMessage[]; + count: number; + hasMore: boolean; +} + +const FindMessages = async ({ + chatId, + ownerId, + pageNumber = "1" +}: Request): Promise => { + const userInChat = await ChatUser.count({ + where: { chatId, userId: ownerId } + }); + + if (userInChat === 0) { + throw new AppError("UNAUTHORIZED", 400); + } + + const limit = 20; + const offset = limit * (+pageNumber - 1); + + const { count, rows: records } = await ChatMessage.findAndCountAll({ + where: { + chatId + }, + include: [{ model: User, as: "sender", attributes: ["id", "name"] }], + limit, + offset, + + order: [["createdAt", "DESC"]] + }); + + const hasMore = count > offset + records.length; + + const sorted = sortBy(records, ["id", "ASC"]); + + return { + records: sorted, + count, + hasMore + }; +}; + +export default FindMessages; diff --git a/backend/src/services/ChatService/FindService.ts b/backend/src/services/ChatService/FindService.ts new file mode 100644 index 0000000..c849990 --- /dev/null +++ b/backend/src/services/ChatService/FindService.ts @@ -0,0 +1,26 @@ +import Chat from "../../models/Chat"; +import Company from "../../models/Company"; +import User from "../../models/User"; + +type Params = { + companyId: number; + ownerId?: number; +}; + +const FindService = async ({ ownerId, companyId }: Params): Promise => { + const chats: Chat[] = await Chat.findAll({ + where: { + ownerId, + companyId + }, + include: [ + { model: Company, as: "company", attributes: ["id", "name"] }, + { model: User, as: "owner", attributes: ["id", "name"] } + ], + order: [["createdAt", "DESC"]] + }); + + return chats; +}; + +export default FindService; diff --git a/backend/src/services/ChatService/ListService.ts b/backend/src/services/ChatService/ListService.ts new file mode 100644 index 0000000..38246d0 --- /dev/null +++ b/backend/src/services/ChatService/ListService.ts @@ -0,0 +1,54 @@ +import { Op } from "sequelize"; +import Chat from "../../models/Chat"; +import ChatUser from "../../models/ChatUser"; +import User from "../../models/User"; + +interface Request { + ownerId: number; + pageNumber?: string; +} + +interface Response { + records: Chat[]; + count: number; + hasMore: boolean; +} + +const ListService = async ({ + ownerId, + pageNumber = "1" +}: Request): Promise => { + const chatUsers = await ChatUser.findAll({ + where: { userId: ownerId } + }); + + const chatIds = chatUsers.map(chat => chat.chatId); + + const limit = 20; + const offset = limit * (+pageNumber - 1); + + const { count, rows: records } = await Chat.findAndCountAll({ + where: { + id: { + [Op.in]: chatIds + } + }, + include: [ + { model: User, as: "owner" }, + { model: ChatUser, as: "users", include: [{ model: User, as: "user" }] } + ], + limit, + offset, + order: [["createdAt", "DESC"]] + }); + + const hasMore = count > offset + records.length; + + return { + records, + count, + hasMore + }; +}; + +export default ListService; diff --git a/backend/src/services/ChatService/ShowFromUuidService.ts b/backend/src/services/ChatService/ShowFromUuidService.ts new file mode 100644 index 0000000..dd5f950 --- /dev/null +++ b/backend/src/services/ChatService/ShowFromUuidService.ts @@ -0,0 +1,14 @@ +import Chat from "../../models/Chat"; +import AppError from "../../errors/AppError"; + +const ShowFromUuidService = async (uuid: string): Promise => { + const record = await Chat.findOne({ where: { uuid } }); + + if (!record) { + throw new AppError("ERR_NO_CHAT_FOUND", 404); + } + + return record; +}; + +export default ShowFromUuidService; diff --git a/backend/src/services/ChatService/ShowService.ts b/backend/src/services/ChatService/ShowService.ts new file mode 100644 index 0000000..55be2d2 --- /dev/null +++ b/backend/src/services/ChatService/ShowService.ts @@ -0,0 +1,14 @@ +import Chat from "../../models/Chat"; +import AppError from "../../errors/AppError"; + +const ShowService = async (id: string | number): Promise => { + const record = await Chat.findByPk(id); + + if (!record) { + throw new AppError("ERR_NO_CHAT_FOUND", 404); + } + + return record; +}; + +export default ShowService; diff --git a/backend/src/services/ChatService/UpdateService.ts b/backend/src/services/ChatService/UpdateService.ts new file mode 100644 index 0000000..8ebdad8 --- /dev/null +++ b/backend/src/services/ChatService/UpdateService.ts @@ -0,0 +1,38 @@ +import Chat from "../../models/Chat"; +import ChatUser from "../../models/ChatUser"; +import User from "../../models/User"; + +interface ChatData { + id: number; + title?: string; + users?: any[]; +} + +export default async function UpdateService(data: ChatData) { + const { users } = data; + const record = await Chat.findByPk(data.id, { + include: [{ model: ChatUser, as: "users" }] + }); + const { ownerId } = record; + + await record.update({ title: data.title }); + + if (Array.isArray(users)) { + await ChatUser.destroy({ where: { chatId: record.id } }); + await ChatUser.create({ chatId: record.id, userId: ownerId }); + for (let user of users) { + if (user.id !== ownerId) { + await ChatUser.create({ chatId: record.id, userId: user.id }); + } + } + } + + await record.reload({ + include: [ + { model: ChatUser, as: "users", include: [{ model: User, as: "user" }] }, + { model: User, as: "owner" } + ] + }); + + return record; +} diff --git a/backend/src/services/CompanyService/CreateCompanyService.ts b/backend/src/services/CompanyService/CreateCompanyService.ts new file mode 100644 index 0000000..c7aae04 --- /dev/null +++ b/backend/src/services/CompanyService/CreateCompanyService.ts @@ -0,0 +1,305 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import Company from "../../models/Company"; +import Setting from "../../models/Setting"; +import User from "../../models/User"; + +interface CompanyData { + name: string; + phone?: string; + email?: string; + password?: string; + status?: boolean; + planId?: number; + campaignsEnabled?: boolean; + dueDate?: string; + recurrence?: string; +} + +const CreateCompanyService = async ( + companyData: CompanyData +): Promise => { + const { + name, + phone, + email, + status, + planId, + password, + campaignsEnabled, + dueDate, + recurrence + } = companyData; + + const companySchema = Yup.object().shape({ + name: Yup.string() + .min(2, "ERR_COMPANY_INVALID_NAME") + .required("ERR_COMPANY_INVALID_NAME") + .test( + "Check-unique-name", + "ERR_COMPANY_NAME_ALREADY_EXISTS", + async value => { + if (value) { + const companyWithSameName = await Company.findOne({ + where: { name: value } + }); + + return !companyWithSameName; + } + return false; + } + ) + }); + + try { + await companySchema.validate({ name }); + } catch (err: any) { + throw new AppError(err.message); + } + + const company = await Company.create({ + name, + phone, + email, + status, + planId, + dueDate, + recurrence + }); + + const user = await User.create({ + name: company.name, + email: company.email, + password: password || "mudar123", + profile: "admin", + companyId: company.id + }); + + await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "asaas" + }, + defaults: { + companyId: company.id, + key: "asaas", + value: "" + }, + }); + + //tokenixc + await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "tokenixc" + }, + defaults: { + companyId: company.id, + key: "tokenixc", + value: "" + }, + }); + + //ipixc + await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "ipixc" + }, + defaults: { + companyId: company.id, + key: "ipixc", + value: "" + }, + }); + + //ipmkauth + await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "ipmkauth" + }, + defaults: { + companyId: company.id, + key: "ipmkauth", + value: "" + }, + }); + + //clientsecretmkauth + await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "clientsecretmkauth" + }, + defaults: { + companyId: company.id, + key: "clientsecretmkauth", + value: "" + }, + }); + + //clientidmkauth + await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "clientidmkauth" + }, + defaults: { + companyId: company.id, + key: "clientidmkauth", + value: "" + }, + }); + + //CheckMsgIsGroup + await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "CheckMsgIsGroup" + }, + defaults: { + companyId: company.id, + key: "enabled", + value: "" + }, + }); + + //CheckMsgIsGroup + await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "" + }, + defaults: { + companyId: company.id, + key: "call", + value: "disabled" + }, + }); + + //scheduleType + await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "scheduleType" + }, + defaults: { + companyId: company.id, + key: "scheduleType", + value: "disabled" + }, + }); + + + // Enviar mensagem ao aceitar ticket + await Setting.findOrCreate({ + where:{ + companyId: company.id, + key: "sendGreetingAccepted", + }, + defaults: { + companyId: company.id, + key: "sendGreetingAccepted", + value: "disabled" + }, + }); + + // Enviar mensagem de transferencia + await Setting.findOrCreate({ + where:{ + companyId: company.id, + key: "sendMsgTransfTicket", + }, + defaults: { + companyId: company.id, + key: "sendMsgTransfTicket", + value: "disabled" + }, + }); + + //userRating + await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "userRating" + }, + defaults: { + companyId: company.id, + key: "userRating", + value: "disabled" + }, + }); + + //userRating + await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "chatBotType" + }, + defaults: { + companyId: company.id, + key: "chatBotType", + value: "text" + }, + + }); + + await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "tokensgp" + }, + defaults: { + companyId: company.id, + key: "tokensgp", + value: "" + }, + }); + + await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "ipsgp" + }, + defaults: { + companyId: company.id, + key: "ipsgp", + value: "" + }, + }); + + await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "appsgp" + }, + defaults: { + companyId: company.id, + key: "appsgp", + value: "" + }, + }); + + if (companyData.campaignsEnabled !== undefined) { + const [setting, created] = await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "campaignsEnabled" + }, + defaults: { + companyId: company.id, + key: "campaignsEnabled", + value: `${campaignsEnabled}` + }, + + }); + if (!created) { + await setting.update({ value: `${campaignsEnabled}` }); + } + } + + return company; +}; + +export default CreateCompanyService; diff --git a/backend/src/services/CompanyService/DeleteCompanyService.ts b/backend/src/services/CompanyService/DeleteCompanyService.ts new file mode 100644 index 0000000..c4c9651 --- /dev/null +++ b/backend/src/services/CompanyService/DeleteCompanyService.ts @@ -0,0 +1,16 @@ +import Company from "../../models/Company"; +import AppError from "../../errors/AppError"; + +const DeleteCompanyService = async (id: string): Promise => { + const company = await Company.findOne({ + where: { id } + }); + + if (!company) { + throw new AppError("ERR_NO_COMPANY_FOUND", 404); + } + + await company.destroy(); +}; + +export default DeleteCompanyService; diff --git a/backend/src/services/CompanyService/FindAllCompaniesService.ts b/backend/src/services/CompanyService/FindAllCompaniesService.ts new file mode 100644 index 0000000..e593345 --- /dev/null +++ b/backend/src/services/CompanyService/FindAllCompaniesService.ts @@ -0,0 +1,16 @@ +import Company from "../../models/Company"; +import Plan from "../../models/Plan"; +import Setting from "../../models/Setting"; + +const FindAllCompanyService = async (): Promise => { + const companies = await Company.findAll({ + order: [["name", "ASC"]], + include: [ + { model: Plan, as: "plan", attributes: ["id", "name", "value"] }, + { model: Setting, as: "settings" } + ] + }); + return companies; +}; + +export default FindAllCompanyService; diff --git a/backend/src/services/CompanyService/ListCompaniesPlanService.ts b/backend/src/services/CompanyService/ListCompaniesPlanService.ts new file mode 100644 index 0000000..02076af --- /dev/null +++ b/backend/src/services/CompanyService/ListCompaniesPlanService.ts @@ -0,0 +1,33 @@ +import Company from "../../models/Company"; +import Plan from "../../models/Plan"; + +const ListCompaniesPlanService = async (): Promise => { + const companies = await Company.findAll({ + attributes: ["id", "name", "email", "status", "dueDate", "createdAt", "phone"], + order: [["name", "ASC"]], + include: [ + { + model: Plan, as: "plan", + attributes: [ + "id", + "name", + "users", + "connections", + "queues", + "value", + "useCampaigns", + "useSchedules", + "useInternalChat", + "useExternalApi", + "useKanban", + "useOpenAi", + "useIntegrations", + "useInternal" + ] + }, + ] + }); + return companies; +}; + +export default ListCompaniesPlanService; diff --git a/backend/src/services/CompanyService/ListCompaniesService.ts b/backend/src/services/CompanyService/ListCompaniesService.ts new file mode 100644 index 0000000..69b813f --- /dev/null +++ b/backend/src/services/CompanyService/ListCompaniesService.ts @@ -0,0 +1,50 @@ +import { Sequelize, Op } from "sequelize"; +import Company from "../../models/Company"; + +interface Request { + searchParam?: string; + pageNumber?: string; +} + +interface Response { + companies: Company[]; + count: number; + hasMore: boolean; +} + +const ListCompaniesService = async ({ + searchParam = "", + pageNumber = "1", +}: Request): Promise => { + const whereCondition = { + [Op.or]: [ + { + name: Sequelize.where( + Sequelize.fn("LOWER", Sequelize.col("name")), + "LIKE", + `%${searchParam.toLowerCase().trim()}%` + ) + } + ] + }; + const limit = 20; + const offset = limit * (+pageNumber - 1); + + + const { count, rows: companies } = await Company.findAndCountAll({ + where: whereCondition, + limit, + offset, + order: [["name", "ASC"]] + }); + + const hasMore = count > offset + companies.length; + + return { + companies, + count, + hasMore, + }; +}; + +export default ListCompaniesService; diff --git a/backend/src/services/CompanyService/ShowCompanyService.ts b/backend/src/services/CompanyService/ShowCompanyService.ts new file mode 100644 index 0000000..bede133 --- /dev/null +++ b/backend/src/services/CompanyService/ShowCompanyService.ts @@ -0,0 +1,14 @@ +import Company from "../../models/Company"; +import AppError from "../../errors/AppError"; + +const ShowCompanyService = async (id: string | number): Promise => { + const company = await Company.findByPk(id); + + if (!company) { + throw new AppError("ERR_NO_COMPANY_FOUND", 404); + } + + return company; +}; + +export default ShowCompanyService; diff --git a/backend/src/services/CompanyService/ShowPlanCompanyService.ts b/backend/src/services/CompanyService/ShowPlanCompanyService.ts new file mode 100644 index 0000000..4b91244 --- /dev/null +++ b/backend/src/services/CompanyService/ShowPlanCompanyService.ts @@ -0,0 +1,35 @@ +import Company from "../../models/Company"; +import Plan from "../../models/Plan"; + +const ShowPlanCompanyService = async (id: string | number): Promise => { + const companies = await Company.findOne({ + where: { id }, + attributes: ["id", "name", "email", "status", "dueDate", "createdAt", "phone"], + order: [["name", "ASC"]], + include: [ + { + model: Plan, as: "plan", + attributes: [ + "id", + "name", + "users", + "connections", + "queues", + "value", + "useCampaigns", + "useSchedules", + "useInternalChat", + "useExternalApi", + "useKanban", + "useOpenAi", + "useIntegrations", + "useInternal" + ] + }, + ] + }); + + return companies; +}; + +export default ShowPlanCompanyService; diff --git a/backend/src/services/CompanyService/UpdateCompanyService.ts b/backend/src/services/CompanyService/UpdateCompanyService.ts new file mode 100644 index 0000000..cccb54c --- /dev/null +++ b/backend/src/services/CompanyService/UpdateCompanyService.ts @@ -0,0 +1,102 @@ +import AppError from "../../errors/AppError"; +import Company from "../../models/Company"; +import Setting from "../../models/Setting"; +import Invoices from "../../models/Invoices"; +import Plan from "../../models/Plan"; + +interface CompanyData { + name: string; + id?: number | string; + phone?: string; + email?: string; + status?: boolean; + planId?: number; + campaignsEnabled?: boolean; + dueDate?: string; + recurrence?: string; +} + +const UpdateCompanyService = async ( + companyData: CompanyData +): Promise => { + const company = await Company.findByPk(companyData.id); + const { + name, + phone, + email, + status, + planId, + campaignsEnabled, + dueDate, + recurrence + } = companyData; + + if (!company) { + throw new AppError("ERR_NO_COMPANY_FOUND", 404); + } + + const openInvoices = await Invoices.findAll({ + where: { + status: "open", + companyId: company.id, + }, + }); + + if (openInvoices.length > 1) { + for (const invoice of openInvoices.slice(1)) { + await invoice.update({ status: "cancelled" }); + } +} + +const plan = await Plan.findByPk(planId); + +if (!plan) { + throw new Error("Plano Não Encontrado."); +} + + + // 5. Atualizar a única invoice com status "open" existente, baseada no companyId. + const openInvoice = openInvoices[0]; + + if (openInvoice) { + await openInvoice.update({ + value: plan.value, + detail: plan.name, + dueDate: dueDate, + }); + + } else { + throw new Error("Nenhuma fatura em aberto para este cliente!"); + } + + await company.update({ + name, + phone, + email, + status, + planId, + dueDate, + recurrence + }); + + if (companyData.campaignsEnabled !== undefined) { + const [setting, created] = await Setting.findOrCreate({ + where: { + companyId: company.id, + key: "campaignsEnabled" + }, + defaults: { + companyId: company.id, + key: "campaignsEnabled", + value: `${campaignsEnabled}` + } + }); + if (!created) { + await setting.update({ value: `${campaignsEnabled}` }); + } + } + + return company; +}; + +export default UpdateCompanyService; diff --git a/backend/src/services/CompanyService/UpdateSchedulesService.ts b/backend/src/services/CompanyService/UpdateSchedulesService.ts new file mode 100644 index 0000000..afaef18 --- /dev/null +++ b/backend/src/services/CompanyService/UpdateSchedulesService.ts @@ -0,0 +1,26 @@ +import AppError from "../../errors/AppError"; +import Company from "../../models/Company"; + +type ScheduleData = { + id: number | string; + schedules: []; +}; + +const UpdateSchedulesService = async ({ + id, + schedules +}: ScheduleData): Promise => { + const company = await Company.findByPk(id); + + if (!company) { + throw new AppError("ERR_NO_COMPANY_FOUND", 404); + } + + await company.update({ + schedules + }); + + return company; +}; + +export default UpdateSchedulesService; diff --git a/backend/src/services/CompanyService/VerifyCurrentSchedule.ts b/backend/src/services/CompanyService/VerifyCurrentSchedule.ts new file mode 100644 index 0000000..f8a6bfd --- /dev/null +++ b/backend/src/services/CompanyService/VerifyCurrentSchedule.ts @@ -0,0 +1,54 @@ +import { QueryTypes } from "sequelize"; +import sequelize from "../../database"; + +type Result = { + id: number; + currentSchedule: []; + startTimeA: string; + endTimeA: string; + startTimeB: string | null; + endTimeB: string | null; + inActivity: boolean; +}; + +const VerifyCurrentSchedule = async (id: string | number): Promise => { + const sql = ` + select + s.id, + s.currentWeekday, + s.currentSchedule, + (s.currentSchedule->>'startTimeA')::time "startTimeA", + (s.currentSchedule->>'endTimeA')::time "endTimeA", + coalesce(nullif((s.currentSchedule->>'startTimeB'), ''), '00:00')::time "startTimeB", + coalesce(nullif((s.currentSchedule->>'endTimeB'), ''), '00:00')::time "endTimeB", + ( + now()::time >= (s.currentSchedule->>'startTimeA')::time and + now()::time <= (s.currentSchedule->>'endTimeA')::time or + now()::time >= coalesce(nullif((s.currentSchedule->>'startTimeB'), ''), '00:00')::time and + now()::time <= coalesce(nullif((s.currentSchedule->>'endTimeB'), ''), '00:00')::time + ) "inActivity" + from ( + SELECT + c.id, + to_char(current_date, 'day') currentWeekday, + (array_to_json(array_agg(s))->>0)::jsonb currentSchedule + FROM "Companies" c, jsonb_array_elements(c.schedules) s + WHERE s->>'weekdayEn' like trim(to_char(current_date, 'day')) and c.id = :id + GROUP BY 1, 2 + ) s + where s.currentSchedule->>'startTimeA' not like '' and + s.currentSchedule->>'endTimeA' not like '' or + coalesce(nullif(s.currentSchedule->>'startTimeB', ''), '00:00') not like '' and + coalesce(nullif(s.currentSchedule->>'endTimeB', ''), '00:00') not like ''; + `; + + const result: Result = await sequelize.query(sql, { + replacements: { id }, + type: QueryTypes.SELECT, + plain: true + }); + + return result; +}; + +export default VerifyCurrentSchedule; diff --git a/backend/src/services/ContactListItemService/CreateService.ts b/backend/src/services/ContactListItemService/CreateService.ts new file mode 100644 index 0000000..8b69715 --- /dev/null +++ b/backend/src/services/ContactListItemService/CreateService.ts @@ -0,0 +1,52 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import ContactListItem from "../../models/ContactListItem"; +import { logger } from "../../utils/logger"; +import CheckContactNumber from "../WbotServices/CheckNumber"; + +interface Data { + name: string; + number: string; + contactListId: number; + companyId: number; + email?: string; +} + +const CreateService = async (data: Data): Promise => { + const { name } = data; + + const contactListItemSchema = Yup.object().shape({ + name: Yup.string() + .min(3, "ERR_CONTACTLISTITEM_INVALID_NAME") + .required("ERR_CONTACTLISTITEM_REQUIRED") + }); + + try { + await contactListItemSchema.validate({ name }); + } catch (err: any) { + throw new AppError(err.message); + } + + const [record] = await ContactListItem.findOrCreate({ + where: { + number: data.number, + companyId: data.companyId, + contactListId: data.contactListId + }, + defaults: data + }); + + try { + const response = await CheckContactNumber(record.number, record.companyId); + record.isWhatsappValid = response.exists; + const number = response.jid.replace(/\D/g, ""); + record.number = number; + await record.save(); + } catch (e) { + logger.error(`Número de contato inválido: ${record.number}`); + } + + return record; +}; + +export default CreateService; diff --git a/backend/src/services/ContactListItemService/DeleteService.ts b/backend/src/services/ContactListItemService/DeleteService.ts new file mode 100644 index 0000000..2824a96 --- /dev/null +++ b/backend/src/services/ContactListItemService/DeleteService.ts @@ -0,0 +1,16 @@ +import ContactListItem from "../../models/ContactListItem"; +import AppError from "../../errors/AppError"; + +const DeleteService = async (id: string): Promise => { + const record = await ContactListItem.findOne({ + where: { id } + }); + + if (!record) { + throw new AppError("ERR_NO_CONTACTLISTITEM_FOUND", 404); + } + + await record.destroy(); +}; + +export default DeleteService; diff --git a/backend/src/services/ContactListItemService/FindAllService.ts b/backend/src/services/ContactListItemService/FindAllService.ts new file mode 100644 index 0000000..2e4f158 --- /dev/null +++ b/backend/src/services/ContactListItemService/FindAllService.ts @@ -0,0 +1,10 @@ +import ContactListItem from "../../models/ContactListItem"; + +const FindAllService = async (): Promise => { + const records: ContactListItem[] = await ContactListItem.findAll({ + order: [["name", "ASC"]] + }); + return records; +}; + +export default FindAllService; diff --git a/backend/src/services/ContactListItemService/FindService.ts b/backend/src/services/ContactListItemService/FindService.ts new file mode 100644 index 0000000..e574f38 --- /dev/null +++ b/backend/src/services/ContactListItemService/FindService.ts @@ -0,0 +1,33 @@ +import ContactListItem from "../../models/ContactListItem"; +import Company from "../../models/Company"; + +type Params = { + companyId: number; + contactListId: number; +}; + +const FindService = async ({ + companyId, + contactListId +}: Params): Promise => { + let where: any = { + companyId + }; + + if (contactListId) { + where = { + ...where, + contactListId + }; + } + + const notes: ContactListItem[] = await ContactListItem.findAll({ + where, + include: [{ model: Company, as: "company", attributes: ["id", "name"] }], + order: [["name", "ASC"]] + }); + + return notes; +}; + +export default FindService; diff --git a/backend/src/services/ContactListItemService/ListService.ts b/backend/src/services/ContactListItemService/ListService.ts new file mode 100644 index 0000000..ab1f53f --- /dev/null +++ b/backend/src/services/ContactListItemService/ListService.ts @@ -0,0 +1,57 @@ +import { Sequelize, Op } from "sequelize"; +import ContactListItem from "../../models/ContactListItem"; + +interface Request { + searchParam?: string; + pageNumber?: string; + companyId: number | string; + contactListId: number | string; +} + +interface Response { + contacts: ContactListItem[]; + count: number; + hasMore: boolean; +} + +const ListService = async ({ + searchParam = "", + pageNumber = "1", + companyId, + contactListId +}: Request): Promise => { + const whereCondition = { + [Op.or]: [ + { + name: Sequelize.where( + Sequelize.fn("LOWER", Sequelize.col("name")), + "LIKE", + `%${searchParam.toLowerCase().trim()}%` + ) + }, + { number: { [Op.like]: `%${searchParam.toLowerCase().trim()}%` } } + ], + companyId, + contactListId + }; + + const limit = 20; + const offset = limit * (+pageNumber - 1); + + const { count, rows: contacts } = await ContactListItem.findAndCountAll({ + where: whereCondition, + limit, + offset, + order: [["name", "ASC"]] + }); + + const hasMore = count > offset + contacts.length; + + return { + contacts, + count, + hasMore + }; +}; + +export default ListService; diff --git a/backend/src/services/ContactListItemService/ShowService.ts b/backend/src/services/ContactListItemService/ShowService.ts new file mode 100644 index 0000000..1b09384 --- /dev/null +++ b/backend/src/services/ContactListItemService/ShowService.ts @@ -0,0 +1,14 @@ +import ContactListItem from "../../models/ContactListItem"; +import AppError from "../../errors/AppError"; + +const ShowService = async (id: string | number): Promise => { + const record = await ContactListItem.findByPk(id); + + if (!record) { + throw new AppError("ERR_NO_CONTACTLISTITEM_FOUND", 404); + } + + return record; +}; + +export default ShowService; diff --git a/backend/src/services/ContactListItemService/UpdateService.ts b/backend/src/services/ContactListItemService/UpdateService.ts new file mode 100644 index 0000000..b254eb8 --- /dev/null +++ b/backend/src/services/ContactListItemService/UpdateService.ts @@ -0,0 +1,41 @@ +import AppError from "../../errors/AppError"; +import ContactListItem from "../../models/ContactListItem"; +import { logger } from "../../utils/logger"; +import CheckContactNumber from "../WbotServices/CheckNumber"; + +interface Data { + id: number | string; + name: string; + number: string; + email?: string; +} + +const UpdateService = async (data: Data): Promise => { + const { id, name, number, email } = data; + + const record = await ContactListItem.findByPk(id); + + if (!record) { + throw new AppError("ERR_NO_CONTACTLISTITEM_FOUND", 404); + } + + await record.update({ + name, + number, + email + }); + + try { + const response = await CheckContactNumber(record.number, record.companyId); + record.isWhatsappValid = response.exists; + const number = response.jid.replace(/\D/g, ""); + record.number = number; + await record.save(); + } catch (e) { + logger.error(`Número de contato inválido: ${record.number}`); + } + + return record; +}; + +export default UpdateService; diff --git a/backend/src/services/ContactListService/CreateService.ts b/backend/src/services/ContactListService/CreateService.ts new file mode 100644 index 0000000..fcf7d03 --- /dev/null +++ b/backend/src/services/ContactListService/CreateService.ts @@ -0,0 +1,30 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import ContactList from "../../models/ContactList"; + +interface Data { + name: string; + companyId: number | string; +} + +const CreateService = async (data: Data): Promise => { + const { name, companyId } = data; + + const ticketnoteSchema = Yup.object().shape({ + name: Yup.string() + .min(3, "ERR_CONTACTLIST_INVALID_NAME") + .required("ERR_CONTACTLIST_REQUIRED") + }); + + try { + await ticketnoteSchema.validate({ name }); + } catch (err: any) { + throw new AppError(err.message); + } + + const record = await ContactList.create(data); + + return record; +}; + +export default CreateService; diff --git a/backend/src/services/ContactListService/DeleteService.ts b/backend/src/services/ContactListService/DeleteService.ts new file mode 100644 index 0000000..3550ff3 --- /dev/null +++ b/backend/src/services/ContactListService/DeleteService.ts @@ -0,0 +1,16 @@ +import ContactList from "../../models/ContactList"; +import AppError from "../../errors/AppError"; + +const DeleteService = async (id: string): Promise => { + const record = await ContactList.findOne({ + where: { id } + }); + + if (!record) { + throw new AppError("ERR_NO_CONTACTLIST_FOUND", 404); + } + + await record.destroy(); +}; + +export default DeleteService; diff --git a/backend/src/services/ContactListService/FindAllService.ts b/backend/src/services/ContactListService/FindAllService.ts new file mode 100644 index 0000000..44efebe --- /dev/null +++ b/backend/src/services/ContactListService/FindAllService.ts @@ -0,0 +1,10 @@ +import ContactList from "../../models/ContactList"; + +const FindAllService = async (): Promise => { + const records: ContactList[] = await ContactList.findAll({ + order: [["name", "ASC"]] + }); + return records; +}; + +export default FindAllService; diff --git a/backend/src/services/ContactListService/FindService.ts b/backend/src/services/ContactListService/FindService.ts new file mode 100644 index 0000000..daf7ffd --- /dev/null +++ b/backend/src/services/ContactListService/FindService.ts @@ -0,0 +1,20 @@ +import ContactList from "../../models/ContactList"; +import Company from "../../models/Company"; + +type Params = { + companyId: string; +}; + +const FindService = async ({ companyId }: Params): Promise => { + const notes: ContactList[] = await ContactList.findAll({ + where: { + companyId + }, + include: [{ model: Company, as: "company", attributes: ["id", "name"] }], + order: [["name", "ASC"]] + }); + + return notes; +}; + +export default FindService; diff --git a/backend/src/services/ContactListService/ImportContacts.ts b/backend/src/services/ContactListService/ImportContacts.ts new file mode 100644 index 0000000..a5d2c9b --- /dev/null +++ b/backend/src/services/ContactListService/ImportContacts.ts @@ -0,0 +1,79 @@ +import { head } from "lodash"; +import XLSX from "xlsx"; +import { has } from "lodash"; +import ContactListItem from "../../models/ContactListItem"; +import CheckContactNumber from "../WbotServices/CheckNumber"; +import { logger } from "../../utils/logger"; +// import CheckContactNumber from "../WbotServices/CheckNumber"; + +export async function ImportContacts( + contactListId: number, + companyId: number, + file: Express.Multer.File | undefined +) { + const workbook = XLSX.readFile(file?.path as string); + const worksheet = head(Object.values(workbook.Sheets)) as any; + const rows: any[] = XLSX.utils.sheet_to_json(worksheet, { header: 0 }); + const contacts = rows.map(row => { + let name = ""; + let number = ""; + let email = ""; + + if (has(row, "nome") || has(row, "Nome")) { + name = row["nome"] || row["Nome"]; + } + + if ( + has(row, "numero") || + has(row, "número") || + has(row, "Numero") || + has(row, "Número") + ) { + number = row["numero"] || row["número"] || row["Numero"] || row["Número"]; + number = `${number}`.replace(/\D/g, ""); + } + + if ( + has(row, "email") || + has(row, "e-mail") || + has(row, "Email") || + has(row, "E-mail") + ) { + email = row["email"] || row["e-mail"] || row["Email"] || row["E-mail"]; + } + + return { name, number, email, contactListId, companyId }; + }); + + const contactList: ContactListItem[] = []; + + for (const contact of contacts) { + const [newContact, created] = await ContactListItem.findOrCreate({ + where: { + number: `${contact.number}`, + contactListId: contact.contactListId, + companyId: contact.companyId + }, + defaults: contact + }); + if (created) { + contactList.push(newContact); + } + } + + if (contactList) { + for (let newContact of contactList) { + try { + const response = await CheckContactNumber(newContact.number, companyId); + newContact.isWhatsappValid = response.exists; + const number = response.jid.replace(/\D/g, ""); + newContact.number = number; + await newContact.save(); + } catch (e) { + logger.error(`Número de contato inválido: ${newContact.number}`); + } + } + } + + return contactList; +} diff --git a/backend/src/services/ContactListService/ListService.ts b/backend/src/services/ContactListService/ListService.ts new file mode 100644 index 0000000..f77af09 --- /dev/null +++ b/backend/src/services/ContactListService/ListService.ts @@ -0,0 +1,76 @@ +import { Op, fn, col, where } from "sequelize"; +import ContactList from "../../models/ContactList"; +import ContactListItem from "../../models/ContactListItem"; +import { isEmpty } from "lodash"; + +interface Request { + companyId: number | string; + searchParam?: string; + pageNumber?: string; +} + +interface Response { + records: ContactList[]; + count: number; + hasMore: boolean; +} + +const ListService = async ({ + searchParam = "", + pageNumber = "1", + companyId +}: Request): Promise => { + let whereCondition: any = { + companyId + }; + + if (!isEmpty(searchParam)) { + whereCondition = { + ...whereCondition, + [Op.or]: [ + { + name: where( + fn("LOWER", col("ContactList.name")), + "LIKE", + `%${searchParam.toLowerCase().trim()}%` + ) + } + ] + }; + } + + const limit = 20; + const offset = limit * (+pageNumber - 1); + + const { count, rows: records } = await ContactList.findAndCountAll({ + where: whereCondition, + limit, + offset, + order: [["name", "ASC"]], + subQuery: false, + include: [ + { + model: ContactListItem, + as: "contacts", + attributes: [], + required: false + } + ], + attributes: [ + "id", + "name", + [fn("count", col("contacts.id")), "contactsCount"] + ], + group: ["ContactList.id"] + }); + + const hasMore = count > offset + records.length; + + return { + records, + count, + hasMore + }; +}; + +export default ListService; diff --git a/backend/src/services/ContactListService/ShowService.ts b/backend/src/services/ContactListService/ShowService.ts new file mode 100644 index 0000000..13b11e3 --- /dev/null +++ b/backend/src/services/ContactListService/ShowService.ts @@ -0,0 +1,14 @@ +import ContactList from "../../models/ContactList"; +import AppError from "../../errors/AppError"; + +const ShowService = async (id: string | number): Promise => { + const record = await ContactList.findByPk(id); + + if (!record) { + throw new AppError("ERR_NO_TICKETNOTE_FOUND", 404); + } + + return record; +}; + +export default ShowService; diff --git a/backend/src/services/ContactListService/UpdateService.ts b/backend/src/services/ContactListService/UpdateService.ts new file mode 100644 index 0000000..6c58753 --- /dev/null +++ b/backend/src/services/ContactListService/UpdateService.ts @@ -0,0 +1,25 @@ +import AppError from "../../errors/AppError"; +import ContactList from "../../models/ContactList"; + +interface Data { + id: number | string; + name: string; +} + +const UpdateService = async (data: Data): Promise => { + const { id, name } = data; + + const record = await ContactList.findByPk(id); + + if (!record) { + throw new AppError("ERR_NO_CONTACTLIST_FOUND", 404); + } + + await record.update({ + name + }); + + return record; +}; + +export default UpdateService; diff --git a/backend/src/services/ContactServices/CreateContactService.ts b/backend/src/services/ContactServices/CreateContactService.ts new file mode 100644 index 0000000..985cd7f --- /dev/null +++ b/backend/src/services/ContactServices/CreateContactService.ts @@ -0,0 +1,52 @@ +import AppError from "../../errors/AppError"; +import Contact from "../../models/Contact"; +import ContactCustomField from "../../models/ContactCustomField"; + +interface ExtraInfo extends ContactCustomField { + name: string; + value: string; +} + +interface Request { + name: string; + number: string; + email?: string; + profilePicUrl?: string; + companyId: number; + extraInfo?: ExtraInfo[]; + disableBot?: boolean; +} + +const CreateContactService = async ({ + name, + number, + email = "", + companyId, + extraInfo = [], + disableBot = false +}: Request): Promise => { + const numberExists = await Contact.findOne({ + where: { number, companyId } + }); + + if (numberExists) { + throw new AppError("ERR_DUPLICATED_CONTACT"); + } + + const contact = await Contact.create( + { + name, + number, + email, + extraInfo, + companyId + }, + { + include: ["extraInfo"] + } + ); + + return contact; +}; + +export default CreateContactService; diff --git a/backend/src/services/ContactServices/CreateOrUpdateContactService.ts b/backend/src/services/ContactServices/CreateOrUpdateContactService.ts new file mode 100644 index 0000000..6c15ea3 --- /dev/null +++ b/backend/src/services/ContactServices/CreateOrUpdateContactService.ts @@ -0,0 +1,79 @@ +import { getIO } from "../../libs/socket"; +import Contact from "../../models/Contact"; +import ContactCustomField from "../../models/ContactCustomField"; +import { isNil } from "lodash"; +interface ExtraInfo extends ContactCustomField { + name: string; + value: string; +} + +interface Request { + name: string; + number: string; + isGroup: boolean; + email?: string; + profilePicUrl?: string; + companyId: number; + extraInfo?: ExtraInfo[]; + whatsappId?: number; + disableBot?: boolean; +} + +const CreateOrUpdateContactService = async ({ + name, + number: rawNumber, + profilePicUrl, + isGroup, + email = "", + companyId, + extraInfo = [], + whatsappId, + disableBot = false +}: Request): Promise => { + const number = isGroup ? rawNumber : rawNumber.replace(/[^0-9]/g, ""); + + const io = getIO(); + let contact: Contact | null; + + contact = await Contact.findOne({ + where: { + number, + companyId + } + }); + + if (contact) { + contact.update({ profilePicUrl }); + console.log(contact.whatsappId) + if (isNil(contact.whatsappId === null)) { + contact.update({ + whatsappId + }); + } + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-contact`, { + action: "update", + contact + }); + } else { + contact = await Contact.create({ + name, + number, + profilePicUrl, + email, + isGroup, + extraInfo, + companyId, + whatsappId, + disableBot + }); + + io.to(`company-${companyId}-mainchannel`).emit(`company-${companyId}-contact`, { + action: "create", + contact + }); + } + + return contact; +}; + +export default CreateOrUpdateContactService; diff --git a/backend/src/services/ContactServices/DeleteContactService.ts b/backend/src/services/ContactServices/DeleteContactService.ts new file mode 100644 index 0000000..caaf86a --- /dev/null +++ b/backend/src/services/ContactServices/DeleteContactService.ts @@ -0,0 +1,16 @@ +import Contact from "../../models/Contact"; +import AppError from "../../errors/AppError"; + +const DeleteContactService = async (id: string): Promise => { + const contact = await Contact.findOne({ + where: { id } + }); + + if (!contact) { + throw new AppError("ERR_NO_CONTACT_FOUND", 404); + } + + await contact.destroy(); +}; + +export default DeleteContactService; diff --git a/backend/src/services/ContactServices/GetContactService.ts b/backend/src/services/ContactServices/GetContactService.ts new file mode 100644 index 0000000..7466c54 --- /dev/null +++ b/backend/src/services/ContactServices/GetContactService.ts @@ -0,0 +1,43 @@ +import AppError from "../../errors/AppError"; +import Contact from "../../models/Contact"; +import ContactCustomField from "../../models/ContactCustomField"; +import CreateContactService from "./CreateContactService"; + +interface ExtraInfo extends ContactCustomField { + name: string; + value: string; +} + +interface Request { + name: string; + number: string; + companyId: number; + email?: string; + profilePicUrl?: string; + extraInfo?: ExtraInfo[]; +} + +const GetContactService = async ({ + name, + number, + companyId +}: Request): Promise => { + const numberExists = await Contact.findOne({ + where: { number, companyId } + }); + + if (!numberExists) { + const contact = await CreateContactService({ + name, + number, + companyId + }); + + if (contact == null) throw new AppError("CONTACT_NOT_FIND"); + else return contact; + } + + return numberExists; +}; + +export default GetContactService; diff --git a/backend/src/services/ContactServices/ImportContacts.ts b/backend/src/services/ContactServices/ImportContacts.ts new file mode 100644 index 0000000..d594445 --- /dev/null +++ b/backend/src/services/ContactServices/ImportContacts.ts @@ -0,0 +1,75 @@ +import { head } from "lodash"; +import XLSX from "xlsx"; +import { has } from "lodash"; +import Contact from "../../models/Contact"; +import CheckContactNumber from "../WbotServices/CheckNumber"; +import { logger } from "../../utils/logger"; + +export async function ImportContacts( + companyId: number, + file: Express.Multer.File | undefined +) { + const workbook = XLSX.readFile(file?.path as string); + const worksheet = head(Object.values(workbook.Sheets)) as any; + const rows: any[] = XLSX.utils.sheet_to_json(worksheet, { header: 0 }); + const contacts = rows.map(row => { + let name = ""; + let number = ""; + let email = ""; + + if (has(row, "nome") || has(row, "Nome")) { + name = row["nome"] || row["Nome"]; + } + + if ( + has(row, "numero") || + has(row, "número") || + has(row, "Numero") || + has(row, "Número") + ) { + number = row["numero"] || row["número"] || row["Numero"] || row["Número"]; + number = `${number}`.replace(/\D/g, ""); + } + + if ( + has(row, "email") || + has(row, "e-mail") || + has(row, "Email") || + has(row, "E-mail") + ) { + email = row["email"] || row["e-mail"] || row["Email"] || row["E-mail"]; + } + + return { name, number, email, companyId }; + }); + + const contactList: Contact[] = []; + + for (const contact of contacts) { + const [newContact, created] = await Contact.findOrCreate({ + where: { + number: `${contact.number}`, + companyId: contact.companyId + }, + defaults: contact + }); + if (created) { + contactList.push(newContact); + } + } + + if (contactList) { + for (let newContact of contactList) { + try { + const response = await CheckContactNumber(newContact.number, companyId); + const number = response.jid.replace(/\D/g, ""); + newContact.number = number; + await newContact.save(); + } catch (e) { + logger.error(`Número de contato inválido: ${newContact.number}`); + } + } + } + + return contactList; +} diff --git a/backend/src/services/ContactServices/ListContactsService.ts b/backend/src/services/ContactServices/ListContactsService.ts new file mode 100644 index 0000000..37cc71a --- /dev/null +++ b/backend/src/services/ContactServices/ListContactsService.ts @@ -0,0 +1,63 @@ +import { Sequelize, Op } from "sequelize"; +import Contact from "../../models/Contact"; +import Ticket from "../../models/Ticket"; + +interface Request { + searchParam?: string; + pageNumber?: string; + companyId: number; +} + +interface Response { + contacts: Contact[]; + count: number; + hasMore: boolean; +} + +const ListContactsService = async ({ + searchParam = "", + pageNumber = "1", + companyId +}: Request): Promise => { + const whereCondition = { + [Op.or]: [ + { + name: Sequelize.where( + Sequelize.fn("LOWER", Sequelize.col("name")), + "LIKE", + `%${searchParam.toLowerCase().trim()}%` + ) + }, + { number: { [Op.like]: `%${searchParam.toLowerCase().trim()}%` } } + ], + companyId: { + [Op.eq]: companyId + } + }; + const limit = 30; + const offset = limit * (+pageNumber - 1); + + const { count, rows: contacts } = await Contact.findAndCountAll({ + where: whereCondition, + limit, + include: [ + { + model: Ticket, + as: "tickets", + attributes: ["id", "status", "createdAt", "updatedAt"] + } + ], + offset, + order: [["name", "ASC"]] + }); + + const hasMore = count > offset + contacts.length; + + return { + contacts, + count, + hasMore + }; +}; + +export default ListContactsService; diff --git a/backend/src/services/ContactServices/ShowContactService.ts b/backend/src/services/ContactServices/ShowContactService.ts new file mode 100644 index 0000000..4c23ef4 --- /dev/null +++ b/backend/src/services/ContactServices/ShowContactService.ts @@ -0,0 +1,21 @@ +import Contact from "../../models/Contact"; +import AppError from "../../errors/AppError"; + +const ShowContactService = async ( + id: string | number, + companyId: number +): Promise => { + const contact = await Contact.findByPk(id, { include: ["extraInfo", "whatsapp"] }); + + if (contact?.companyId !== companyId) { + throw new AppError("Não é possível excluir registro de outra empresa"); + } + + if (!contact) { + throw new AppError("ERR_NO_CONTACT_FOUND", 404); + } + + return contact; +}; + +export default ShowContactService; diff --git a/backend/src/services/ContactServices/SimpleListService.ts b/backend/src/services/ContactServices/SimpleListService.ts new file mode 100644 index 0000000..12608ed --- /dev/null +++ b/backend/src/services/ContactServices/SimpleListService.ts @@ -0,0 +1,39 @@ +import Contact from "../../models/Contact"; +import AppError from "../../errors/AppError"; +import { FindOptions, Op } from "sequelize"; + +export interface SearchContactParams { + companyId: string | number; + name?: string; +} + +const SimpleListService = async ({ name, companyId }: SearchContactParams): Promise => { + let options: FindOptions = { + order: [ + ['name', 'ASC'] + ] + } + + if (name) { + options.where = { + name: { + [Op.like]: `%${name}%` + } + } + } + + options.where = { + ...options.where, + companyId + } + + const contacts = await Contact.findAll(options); + + if (!contacts) { + throw new AppError("ERR_NO_CONTACT_FOUND", 404); + } + + return contacts; +}; + +export default SimpleListService; diff --git a/backend/src/services/ContactServices/UpdateContactService.ts b/backend/src/services/ContactServices/UpdateContactService.ts new file mode 100644 index 0000000..ef5ab0c --- /dev/null +++ b/backend/src/services/ContactServices/UpdateContactService.ts @@ -0,0 +1,80 @@ +import AppError from "../../errors/AppError"; +import Contact from "../../models/Contact"; +import ContactCustomField from "../../models/ContactCustomField"; + +interface ExtraInfo { + id?: number; + name: string; + value: string; +} +interface ContactData { + email?: string; + number?: string; + name?: string; + active?: boolean; + extraInfo?: ExtraInfo[]; + disableBot?: boolean +} + +interface Request { + contactData: ContactData; + contactId: string; + companyId: number; +} + +const UpdateContactService = async ({ + contactData, + contactId, + companyId +}: Request): Promise => { + const { email, name, number, extraInfo, active, disableBot } = contactData; + + const contact = await Contact.findOne({ + where: { id: contactId }, + attributes: ["id", "name", "number", "email", "companyId", "profilePicUrl", "active","messengerId", "instagramId"], + include: ["extraInfo"] + }); + + if (contact?.companyId !== companyId) { + throw new AppError("Não é possível alterar registros de outra empresa"); + } + + if (!contact) { + throw new AppError("ERR_NO_CONTACT_FOUND", 404); + } + + if (extraInfo) { + await Promise.all( + extraInfo.map(async (info: any) => { + await ContactCustomField.upsert({ ...info, contactId: contact.id }); + }) + ); + + await Promise.all( + contact.extraInfo.map(async oldInfo => { + const stillExists = extraInfo.findIndex(info => info.id === oldInfo.id); + + if (stillExists === -1) { + await ContactCustomField.destroy({ where: { id: oldInfo.id } }); + } + }) + ); + } + + await contact.update({ + name, + number, + email, + active, + disableBot + }); + + await contact.reload({ + attributes: ["id", "name", "number", "email", "profilePicUrl","active","messengerId", "instagramId"], + include: ["extraInfo"] + }); + + return contact; +}; + +export default UpdateContactService; diff --git a/backend/src/services/FileServices/CreateService.ts b/backend/src/services/FileServices/CreateService.ts new file mode 100644 index 0000000..2e7356e --- /dev/null +++ b/backend/src/services/FileServices/CreateService.ts @@ -0,0 +1,68 @@ +import * as Yup from "yup"; + +import AppError from "../../errors/AppError"; +import Files from "../../models/Files"; +import FilesOptions from "../../models/FilesOptions"; +import ShowService from "./ShowService"; + +interface Request { + name: string; + companyId: number; + message: string; + options?: FilesOptions[]; +} + +const CreateService = async ({ + name, + message, + companyId, + options +}: Request): Promise => { + const schema = Yup.object().shape({ + name: Yup.string() + .required() + .min(3) + .test( + "Check-unique-name", + "ERR_RATING_NAME_ALREADY_EXISTS", + async value => { + if (value) { + const tagWithSameName = await Files.findOne({ + where: { name: value, companyId } + }); + + return !tagWithSameName; + } + return false; + } + ) + }); + + try { + await schema.validate({ name }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (err: any) { + throw new AppError(err.message); + } + let fileList = await Files.create({ + name, + message, + companyId + }); + + if(options && options.length > 0) { + await Promise.all( + options.map(async info => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + await FilesOptions.upsert({ ...info, fileId: fileList.id }); + }) + ); + } + + fileList = await ShowService(fileList.id, companyId) + + return fileList; +}; + +export default CreateService; \ No newline at end of file diff --git a/backend/src/services/FileServices/DeleteAllService.ts b/backend/src/services/FileServices/DeleteAllService.ts new file mode 100644 index 0000000..46736b4 --- /dev/null +++ b/backend/src/services/FileServices/DeleteAllService.ts @@ -0,0 +1,16 @@ +import Files from "../../models/Files"; +import AppError from "../../errors/AppError"; + +const DeleteAllService = async (companyId: number): Promise => { + await Files.findAll({ + where: { companyId } + }); + + if (!Files) { + throw new AppError("ERR_NO_RATING_FOUND", 404); + } + + await Files.destroy({ where: {} }); +}; + +export default DeleteAllService; diff --git a/backend/src/services/FileServices/DeleteService.ts b/backend/src/services/FileServices/DeleteService.ts new file mode 100644 index 0000000..55078f3 --- /dev/null +++ b/backend/src/services/FileServices/DeleteService.ts @@ -0,0 +1,16 @@ +import Files from "../../models/Files"; +import AppError from "../../errors/AppError"; + +const DeleteService = async (id: string | number, companyId: number): Promise => { + const file = await Files.findOne({ + where: { id, companyId } + }); + + if (!file) { + throw new AppError("ERR_NO_RATING_FOUND", 404); + } + + await file.destroy(); +}; + +export default DeleteService; diff --git a/backend/src/services/FileServices/ListService.ts b/backend/src/services/FileServices/ListService.ts new file mode 100644 index 0000000..062e49b --- /dev/null +++ b/backend/src/services/FileServices/ListService.ts @@ -0,0 +1,46 @@ +import { Op } from "sequelize"; +import Files from "../../models/Files"; + +interface Request { + companyId: number; + searchParam?: string; + pageNumber?: string | number; +} + +interface Response { + files: Files[]; + count: number; + hasMore: boolean; +} + +const ListService = async ({ + searchParam, + pageNumber = "1", + companyId +}: Request): Promise => { + let whereCondition = {}; + const limit = 20; + const offset = limit * (+pageNumber - 1); + + if (searchParam) { + whereCondition = { + [Op.or]: [{ name: { [Op.like]: `%${searchParam}%` } }] + }; + } + const { count, rows: files } = await Files.findAndCountAll({ + where: {companyId, ...whereCondition}, + limit, + offset, + order: [["name", "ASC"]] + }); + + const hasMore = count > offset + files.length; + + return { + files, + count, + hasMore + }; +}; + +export default ListService; diff --git a/backend/src/services/FileServices/ShowService.ts b/backend/src/services/FileServices/ShowService.ts new file mode 100644 index 0000000..6684c0b --- /dev/null +++ b/backend/src/services/FileServices/ShowService.ts @@ -0,0 +1,25 @@ +import Files from "../../models/Files"; +import AppError from "../../errors/AppError"; +import FilesOptions from "../../models/FilesOptions"; + +const ShowFileService = async (id: string | number, companyId: number): Promise => { + const fileList = await Files.findOne({ + where: { id, companyId }, + include: [ + "options", + { + model: FilesOptions, + as: "options", + order: [["id","ASC"]] + } + ] + }); + + if (!fileList) { + throw new AppError("ERR_NO_FILE_FOUND", 404); + } + + return fileList; +}; + +export default ShowFileService; diff --git a/backend/src/services/FileServices/SimpleListService.ts b/backend/src/services/FileServices/SimpleListService.ts new file mode 100644 index 0000000..fb027f7 --- /dev/null +++ b/backend/src/services/FileServices/SimpleListService.ts @@ -0,0 +1,30 @@ +import { Op } from "sequelize"; +import Rating from "../../models/Files"; + +interface Request { + companyId: number + searchParam?: string; +} + +const ListService = async ({ searchParam, companyId }: Request): Promise => { + let whereCondition = {}; + + if (searchParam) { + whereCondition = { + [Op.or]: [{ name: { [Op.like]: `%${searchParam}%` } }] + }; + } + + const ratings = await Rating.findAll({ + where: {companyId, ...whereCondition}, + order: [["name", "ASC"]], + attributes: { + exclude: ["createdAt", "updatedAt"] + }, + group: ["Rating.id"] + }); + + return ratings; +}; + +export default ListService; diff --git a/backend/src/services/FileServices/UpdateService.ts b/backend/src/services/FileServices/UpdateService.ts new file mode 100644 index 0000000..7946cd7 --- /dev/null +++ b/backend/src/services/FileServices/UpdateService.ts @@ -0,0 +1,82 @@ +import * as Yup from "yup"; + +import AppError from "../../errors/AppError"; +import Files from "../../models/Files"; +import FilesOptions from "../../models/FilesOptions"; +import ShowService from "./ShowService"; + +interface Options { + id?: number; + name: string; + path: string; +} + +interface FileData { + id?: number; + name: string; + message: string; + options?: Options[]; +} + +interface Request { + fileData: FileData; + id: string | number; + companyId: number; +} + +const UpdateService = async ({ + fileData, + id, + companyId +}: Request): Promise => { + const file = await ShowService(id, companyId); + + const schema = Yup.object().shape({ + name: Yup.string().min(3) + }); + + const { name, message, options } = fileData; + + try { + await schema.validate({ name }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (err: any) { + throw new AppError(err.message); + } + + if (options) { + await Promise.all( + options.map(async info => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + await FilesOptions.upsert({ ...info, fileId: file.id }); + }) + ); + + await Promise.all( + file.options.map(async oldInfo => { + const stillExists = options.findIndex(info => info.id === oldInfo.id); + + if (stillExists === -1) { + await FilesOptions.destroy({ where: { id: oldInfo.id } }); + } + }) + ); + } + + + + + await file.update({ + name, + message + }); + + await file.reload({ + attributes: ["id", "name", "message","companyId"], + include: ["options"] + }); + return file; +}; + +export default UpdateService; diff --git a/backend/src/services/ForgotPassWordServices/SendMail.ts b/backend/src/services/ForgotPassWordServices/SendMail.ts new file mode 100644 index 0000000..70cd870 --- /dev/null +++ b/backend/src/services/ForgotPassWordServices/SendMail.ts @@ -0,0 +1,248 @@ +import nodemailer from "nodemailer"; +import sequelize from "sequelize"; +import database from "../../database"; +import Setting from "../../models/Setting"; +import { config } from "dotenv"; +config(); +interface UserData { + companyId: number; +} +const SendMail = async (email: string, tokenSenha: string) => { + const { hasResult, data } = await filterEmail(email); + if (!hasResult) { + return { status: 404, message: "Email não encontrado" }; + } + const userData = data[0][0] as UserData; + if (!userData || userData.companyId === undefined) { + return { status: 404, message: "Dados do usuário não encontrados" }; + } + const companyId = userData.companyId; + const urlSmtp = process.env.MAIL_HOST; + const userSmtp = process.env.MAIL_USER; + const passwordSmpt = process.env.MAIL_PASS; + const fromEmail = process.env.MAIL_FROM; + const transporter = nodemailer.createTransport({ + host: urlSmtp, + port: Number(process.env.MAIL_PORT), + secure: true, + auth: { user: userSmtp, pass: passwordSmpt } + }); + if (hasResult === true) { + const { hasResults, datas } = await insertToken(email, tokenSenha); + async function sendEmail() { + try { + const mailOptions = { + from: fromEmail, + to: email, + subject: "Redefinição de Senha - Whaticket", + html: ` + + + + + + + + Novo modelo + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + + +
+ + + + +
+ + + + + + + +

Bem-vindo à whaticket

Você solicitou recuperação de senha do Whaticket!

+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + +

Código de Verificação:

${tokenSenha}

+ + + + +
+ + + + +
+ + + + +
+ + + + + + + +

Está com dúvidas?

Entre em contato agora mesmo conosco.

+
+ +` + }; + const info = await transporter.sendMail(mailOptions); + console.log("E-mail enviado: " + info.response); + } catch (error) { + console.log(error); + } + } + sendEmail(); + } +}; +const filterEmail = async (email: string) => { + const sql = `SELECT * FROM "Users" WHERE email ='${email}'`; + const result = await database.query(sql, { + type: sequelize.QueryTypes.SELECT + }); + return { hasResult: result.length > 0, data: [result] }; +}; +const insertToken = async (email: string, tokenSenha: string) => { + const sqls = `UPDATE "Users" SET "resetPassword"= '${tokenSenha}' WHERE email ='${email}'`; + const results = await database.query(sqls, { + type: sequelize.QueryTypes.UPDATE + }); + return { hasResults: results.length > 0, datas: results }; +}; +export default SendMail; diff --git a/backend/src/services/HelpServices/CreateService.ts b/backend/src/services/HelpServices/CreateService.ts new file mode 100644 index 0000000..a444df4 --- /dev/null +++ b/backend/src/services/HelpServices/CreateService.ts @@ -0,0 +1,33 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import Help from "../../models/Help"; + +interface Data { + title: string; + description?: string; + video?: string; + link?: string; +} + +const CreateService = async (data: Data): Promise => { + const { title, description } = data; + + const helpSchema = Yup.object().shape({ + title: Yup.string() + .min(3, "ERR_HELP_INVALID_NAME") + .required("ERR_HELP_REQUIRED"), + description: Yup.string().min(3, "ERR_HELP_INVALID_NAME") + }); + + try { + await helpSchema.validate({ title, description }); + } catch (err) { + throw new AppError(err.message); + } + + const record = await Help.create(data); + + return record; +}; + +export default CreateService; diff --git a/backend/src/services/HelpServices/DeleteService.ts b/backend/src/services/HelpServices/DeleteService.ts new file mode 100644 index 0000000..e922ea5 --- /dev/null +++ b/backend/src/services/HelpServices/DeleteService.ts @@ -0,0 +1,16 @@ +import Help from "../../models/Help"; +import AppError from "../../errors/AppError"; + +const DeleteService = async (id: string): Promise => { + const record = await Help.findOne({ + where: { id } + }); + + if (!record) { + throw new AppError("ERR_NO_HELP_FOUND", 404); + } + + await record.destroy(); +}; + +export default DeleteService; diff --git a/backend/src/services/HelpServices/FindAllService.ts b/backend/src/services/HelpServices/FindAllService.ts new file mode 100644 index 0000000..ea6262d --- /dev/null +++ b/backend/src/services/HelpServices/FindAllService.ts @@ -0,0 +1,10 @@ +import Help from "../../models/Help"; + +const FindAllService = async (): Promise => { + const records: Help[] = await Help.findAll({ + order: [["title", "ASC"]] + }); + return records; +}; + +export default FindAllService; diff --git a/backend/src/services/HelpServices/FindService.ts b/backend/src/services/HelpServices/FindService.ts new file mode 100644 index 0000000..b3d3401 --- /dev/null +++ b/backend/src/services/HelpServices/FindService.ts @@ -0,0 +1,11 @@ +import Help from "../../models/Help"; + +const FindService = async (): Promise => { + const notes: Help[] = await Help.findAll({ + order: [["title", "ASC"]] + }); + + return notes; +}; + +export default FindService; diff --git a/backend/src/services/HelpServices/ListService.ts b/backend/src/services/HelpServices/ListService.ts new file mode 100644 index 0000000..5ab1dd5 --- /dev/null +++ b/backend/src/services/HelpServices/ListService.ts @@ -0,0 +1,49 @@ +import { Sequelize, Op } from "sequelize"; +import Help from "../../models/Help"; + +interface Request { + searchParam?: string; + pageNumber?: string; +} + +interface Response { + records: Help[]; + count: number; + hasMore: boolean; +} + +const ListService = async ({ + searchParam = "", + pageNumber = "1" +}: Request): Promise => { + const whereCondition = { + [Op.or]: [ + { + title: Sequelize.where( + Sequelize.fn("LOWER", Sequelize.col("title")), + "LIKE", + `%${searchParam.toLowerCase().trim()}%` + ) + } + ] + }; + const limit = 20; + const offset = limit * (+pageNumber - 1); + + const { count, rows: records } = await Help.findAndCountAll({ + where: whereCondition, + limit, + offset, + order: [["title", "ASC"]] + }); + + const hasMore = count > offset + records.length; + + return { + records, + count, + hasMore + }; +}; + +export default ListService; diff --git a/backend/src/services/HelpServices/ShowService.ts b/backend/src/services/HelpServices/ShowService.ts new file mode 100644 index 0000000..8e38638 --- /dev/null +++ b/backend/src/services/HelpServices/ShowService.ts @@ -0,0 +1,14 @@ +import Help from "../../models/Help"; +import AppError from "../../errors/AppError"; + +const ShowService = async (id: string | number): Promise => { + const record = await Help.findByPk(id); + + if (!record) { + throw new AppError("ERR_NO_HELP_FOUND", 404); + } + + return record; +}; + +export default ShowService; diff --git a/backend/src/services/HelpServices/UpdateService.ts b/backend/src/services/HelpServices/UpdateService.ts new file mode 100644 index 0000000..d4bc4b2 --- /dev/null +++ b/backend/src/services/HelpServices/UpdateService.ts @@ -0,0 +1,26 @@ +import AppError from "../../errors/AppError"; +import Help from "../../models/Help"; + +interface Data { + id: number | string; + title: string; + description?: string; + video?: string; + link?: string; +} + +const UpdateService = async (data: Data): Promise => { + const { id } = data; + + const record = await Help.findByPk(id); + + if (!record) { + throw new AppError("ERR_NO_HELP_FOUND", 404); + } + + await record.update(data); + + return record; +}; + +export default UpdateService; diff --git a/backend/src/services/HubNotificaMeService/CreateService.ts b/backend/src/services/HubNotificaMeService/CreateService.ts new file mode 100644 index 0000000..c517ffc --- /dev/null +++ b/backend/src/services/HubNotificaMeService/CreateService.ts @@ -0,0 +1,47 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import HubNotificaMe from "../../models/HubNotificaMe"; +import Whatsapp from "../../models/Whatsapp"; // Importando a tabela Whatsapps + +interface Data { + nome: string; + token: string; + companyId: number | string; + tipo: string; +} + +const CreateService = async (data: Data): Promise => { + const { nome, token, tipo, companyId } = data; + + // Validação do token + const schema = Yup.object().shape({ + token: Yup.string() + .min(6, "ERR_HUBNOTIFICAME_INVALID_TOKEN") + .required("ERR_HUBNOTIFICAME_REQUIRED") + }); + + try { + await schema.validate({ token }); + } catch (err: any) { + throw new AppError(err.message); + } + + // Criando o registro na tabela HubNotificaMe + const record = await HubNotificaMe.create({ ...data, tipo }); + + + // Criando o registro na tabela Whatsapp + const whatsappRecord = await Whatsapp.create({ + qrcode: token, // Mesma informação do token + status: "CONNECTED", // Status fixo + createdAt: new Date(), // Data e hora atual + updatedAt: new Date(), // Data e hora atual + name: nome, // Mesmo valor de nome + companyId: companyId, // Pega da requisição + type: tipo, // Mesmo valor de tipo + }); + + return record; +}; + +export default CreateService; diff --git a/backend/src/services/HubNotificaMeService/DeleteService.ts b/backend/src/services/HubNotificaMeService/DeleteService.ts new file mode 100644 index 0000000..26ff896 --- /dev/null +++ b/backend/src/services/HubNotificaMeService/DeleteService.ts @@ -0,0 +1,20 @@ +import HubNotificaMe from "../../models/HubNotificaMe"; +import AppError from "../../errors/AppError"; +import Whatsapp from "../../models/Whatsapp"; // Importando a tabela Whatsapps + +const DeleteService = async (id: string): Promise => { + // Busca o registro em HubNotificaMe pelo ID + const record = await HubNotificaMe.findOne({ where: { id } }); + + if (!record) { + throw new AppError("ERR_NO_HUBNOTIFICAME_FOUND", 404); + } + + // Deleta da tabela Whatsapps onde qrcode = token do HubNotificaMe encontrado + await Whatsapp.destroy({ where: { qrcode: record.token } }); + + // Agora remove o registro da HubNotificaMe + await record.destroy(); +}; + +export default DeleteService; diff --git a/backend/src/services/HubNotificaMeService/FindAllService.ts b/backend/src/services/HubNotificaMeService/FindAllService.ts new file mode 100644 index 0000000..d9faf64 --- /dev/null +++ b/backend/src/services/HubNotificaMeService/FindAllService.ts @@ -0,0 +1,10 @@ +import HubNotificaMe from "../../models/HubNotificaMe"; + +const FindAllService = async (): Promise => { + const records: HubNotificaMe[] = await HubNotificaMe.findAll({ + order: [["tipo", "ASC"]] // Ordenando pelo token, por exemplo + }); + return records; +}; + +export default FindAllService; diff --git a/backend/src/services/HubNotificaMeService/FindService.ts b/backend/src/services/HubNotificaMeService/FindService.ts new file mode 100644 index 0000000..ef4c1c8 --- /dev/null +++ b/backend/src/services/HubNotificaMeService/FindService.ts @@ -0,0 +1,21 @@ +import { Op } from "sequelize"; +import HubNotificaMe from "../../models/HubNotificaMe"; +import Company from "../../models/Company"; + +type Params = { + companyId: string; +}; + +const FindService = async ({ companyId }: Params): Promise => { + const records: HubNotificaMe[] = await HubNotificaMe.findAll({ + where: { + companyId + }, + include: [{ model: Company, as: "company", attributes: ["id", "name"] }], + order: [["id", "ASC"]] + }); + + return records; +}; + +export default FindService; diff --git a/backend/src/services/HubNotificaMeService/ListService.ts b/backend/src/services/HubNotificaMeService/ListService.ts new file mode 100644 index 0000000..5fe6b1d --- /dev/null +++ b/backend/src/services/HubNotificaMeService/ListService.ts @@ -0,0 +1,64 @@ +import { Sequelize, Op, Filterable } from "sequelize"; +import HubNotificaMe from "../../models/HubNotificaMe"; // Alterado para o modelo HubNotificaMe + +interface Request { + searchParam?: string; + pageNumber?: string; + companyId: number | string; +} + +interface Response { + records: HubNotificaMe[]; // Alterado para o tipo HubNotificaMe + count: number; + hasMore: boolean; +} + +const ListService = async ({ + searchParam = "", + pageNumber = "1", + companyId +}: Request): Promise => { + const sanitizedSearchParam = searchParam.toLocaleLowerCase().trim(); + + // Condições de filtro baseadas no searchParam + let whereCondition: Filterable["where"] = { + [Op.or]: [ + { + nome: Sequelize.where(Sequelize.fn("LOWER", Sequelize.col("nome")), "LIKE", `%${sanitizedSearchParam}%`) + }, + { + token: Sequelize.where(Sequelize.fn("LOWER", Sequelize.col("token")), "LIKE", `%${sanitizedSearchParam}%`) + }, + { + tipo: Sequelize.where(Sequelize.fn("LOWER", Sequelize.col("tipo")), "LIKE", `%${sanitizedSearchParam}%`) + } + ] + }; + + whereCondition = { + ...whereCondition, + companyId + }; + + // Paginação + const limit = 20; + const offset = limit * (+pageNumber - 1); + + // Buscando registros com base na condição de filtro + const { count, rows: records } = await HubNotificaMe.findAndCountAll({ + where: whereCondition, + limit, + offset, + order: [["tipo", "ASC"]] // Ordenando por token, mas você pode ajustar conforme necessário + }); + + const hasMore = count > offset + records.length; + + return { + records, + count, + hasMore + }; +}; + +export default ListService; diff --git a/backend/src/services/HubNotificaMeService/ShowService.ts b/backend/src/services/HubNotificaMeService/ShowService.ts new file mode 100644 index 0000000..1cd5d7d --- /dev/null +++ b/backend/src/services/HubNotificaMeService/ShowService.ts @@ -0,0 +1,16 @@ +import HubNotificaMe from "../../models/HubNotificaMe"; // Substituímos QuickMessage por HubNotificaMe +import AppError from "../../errors/AppError"; + +const ShowService = async (id: string | number): Promise => { + // Buscando o registro na tabela HubNotificaMe pelo ID + const record = await HubNotificaMe.findByPk(id); + + // Verificando se o registro foi encontrado + if (!record) { + throw new AppError("ERR_NO_RECORD_FOUND", 404); // Mensagem de erro personalizada + } + + return record; // Retorna o registro encontrado +}; + +export default ShowService; diff --git a/backend/src/services/HubNotificaMeService/UpdateService.ts b/backend/src/services/HubNotificaMeService/UpdateService.ts new file mode 100644 index 0000000..72c4fea --- /dev/null +++ b/backend/src/services/HubNotificaMeService/UpdateService.ts @@ -0,0 +1,27 @@ +import AppError from "../../errors/AppError"; +import HubNotificaMe from "../../models/HubNotificaMe"; + +interface Data { + nome: string; + token: string; + id?: number | string; +} + +const UpdateService = async (data: Data): Promise => { + const { id, nome, token } = data; + + const record = await HubNotificaMe.findByPk(id); + + if (!record) { + throw new AppError("ERR_NO_TICKETNOTE_FOUND", 404); + } + + await record.update({ + nome, + token + }); + + return record; +}; + +export default UpdateService; diff --git a/backend/src/services/HubServices/CreateHubChannelsService.ts b/backend/src/services/HubServices/CreateHubChannelsService.ts new file mode 100644 index 0000000..74533b8 --- /dev/null +++ b/backend/src/services/HubServices/CreateHubChannelsService.ts @@ -0,0 +1,40 @@ +import Whatsapp from "../../models/Whatsapp"; +import { IChannel } from "../../controllers/ChannelHubController"; +import { getIO } from "../../libs/socket"; + +// Interface de entrada +interface Request { + channels: IChannel[]; + companyId: number; // Adicionando companyId +} + +// Interface de saída +interface Response { + whatsapps: Whatsapp[]; +} + +// Serviço para criar canais +const CreateChannelsService = async ({ + channels, + companyId, // Recebendo companyId como parâmetro +}: Request): Promise => { + + // Mapeando os canais e atribuindo o companyId + channels = channels.map(channel => { + return { + ...channel, + type: channel.channel, + qrcode: channel.id, + status: "CONNECTED", + companyId: companyId, // Incluindo o companyId + }; + }); + + // Criando múltiplos registros de WhatsApp + const whatsapps = await Whatsapp.bulkCreate(channels); + + // Retornando os whatsapps criados + return { whatsapps }; +}; + +export default CreateChannelsService; \ No newline at end of file diff --git a/backend/src/services/HubServices/CreateHubMessageService.ts b/backend/src/services/HubServices/CreateHubMessageService.ts new file mode 100644 index 0000000..dbe1c44 --- /dev/null +++ b/backend/src/services/HubServices/CreateHubMessageService.ts @@ -0,0 +1,130 @@ +import { getIO } from "../../libs/socket"; +import Message from "../../models/Message"; +import Ticket from "../../models/Ticket"; +import Whatsapp from "../../models/Whatsapp"; + +interface MessageData { + id: string; + contactId: number; + body: string; + ticketId: number; + fromMe: boolean; + queueId?: number; + fileName?: string; + mediaType?: string; + originalName?: string; + companyId: number; // Adicionando o companyId aqui +} + +const CreateMessageService = async (messageData: MessageData): Promise => { + + console.log("creating message"); + console.log({messageData}); + + const { + id, + contactId, + body, + ticketId, + fromMe, + fileName, + mediaType, + originalName, + companyId // Adicionando companyId + } = messageData; + + // Verificando se a mensagem ou arquivo está vazio + if ((!body || body === "") && (!fileName || fileName === "")) { + return; + } + + const data: any = { + id, + contactId, + body, + ticketId, + fromMe, + ack: 2, + companyId // Incluindo companyId no objeto de dados + }; + + if (fileName) { + data.mediaUrl = fileName; + data.mediaType = mediaType === "photo" ? "image" : mediaType; + data.body = data.mediaUrl; + + console.log("MEDIA TYPE DENTRO DO CREATEHUBMESSAGESERVICE:", data.mediaType); + } + + try { + + const newMessage = await Message.create(data); // Salvando a mensagem no banco de dados + + // LOG: Verificar a nova mensagem criada + console.log("Nova mensagem criada:", newMessage); + + const message = await Message.findByPk(messageData.id, { + include: [ + "contact", + { + model: Ticket, + as: "ticket", + include: [ + "contact", "queue", + { + model: Whatsapp, + as: "whatsapp", + attributes: ["name"] + } + ] + }, + { + model: Message, + as: "quotedMsg", + include: ["contact"] + } + ] + }); + + console.log("Mensagem buscada do banco:", message); + + if (message.ticket.queueId !== null && message.queueId === null) { + await message.update({ queueId: message.ticket.queueId }); + } + + if (!message) { + throw new Error("ERR_CREATING_MESSAGE"); + } + + + if (message) { + + console.log("Mensagem emitida pelo WebSocket:", { + action: "create", + message, + ticket: message.ticket, + contact: message.ticket.contact + }); + + const io = getIO(); + io.to(message.ticketId.toString()) + .to(`company-${companyId}-${message.ticket.status}`) + .to(`company-${companyId}-notification`) + .to(`queue-${message.ticket.queueId}-${message.ticket.status}`) + .to(`queue-${message.ticket.queueId}-notification`) + .emit(`company-${companyId}-appMessage`, { + action: "create", + message, + ticket: message.ticket, + contact: message.ticket.contact + }); + } + + return message; + } catch (error) { + console.error("Erro ao criar mensagem:", error); + return null; + } +}; + +export default CreateMessageService; \ No newline at end of file diff --git a/backend/src/services/HubServices/CreateHubTicketService.ts b/backend/src/services/HubServices/CreateHubTicketService.ts new file mode 100644 index 0000000..4e29f0b --- /dev/null +++ b/backend/src/services/HubServices/CreateHubTicketService.ts @@ -0,0 +1,79 @@ +import AppError from "../../errors/AppError"; +import CheckContactOpenTickets from "../../helpers/CheckContactOpenTickets"; +import Ticket from "../../models/Ticket"; +import User from "../../models/User"; +import Whatsapp from "../../models/Whatsapp"; +import ShowContactService from "../ContactServices/ShowContactService"; +import { getIO } from "../../libs/socket"; + +interface Request { + contactId: number; + status: string; + userId: number; + companyId: number; + queueId?: number; + channel: string; +} + +const CreateTicketService = async ({ + contactId, + status, + userId, + companyId, + queueId, + channel +}: Request): Promise => { + + let connectionType; + +if (channel === 'instagram') { + connectionType = 'instagram'; +} else if (channel === 'facebook') { + connectionType = 'facebook'; +} + + const connection = await Whatsapp.findOne({ + where: { type: connectionType! } + }); + + if (!connection) { + throw new Error("Connection id not found"); + } + + // Verificação do companyId recebido + console.log("companyId recebido:", companyId); + + + await CheckContactOpenTickets(contactId, String(connection.id)); + + // Obtendo as informações do contato com base no companyId do usuário + const { isGroup } = await ShowContactService(contactId, companyId); + + if (queueId === undefined) { + const user = await User.findByPk(userId, { include: ["queues"] }); + queueId = user?.queues.length === 1 ? user.queues[0].id : undefined; + } + + // Criando um novo ticket com o companyId associado + const newTicket = await Ticket.create({ + status, + //lastMessage: null, + lastMessage: null, // Adicionando a última mensagem + contactId, + isGroup, + whatsappId: connection.id, + companyId // Passando o companyId para garantir que o ticket pertença à empresa do usuário + }); + + const ticket = await Ticket.findByPk(newTicket.id, { include: ["contact"] }); + + if (!ticket) { + throw new AppError("ERR_CREATING_TICKET"); + } + + const io = getIO(); + + return ticket; +}; + +export default CreateTicketService; diff --git a/backend/src/services/HubServices/CreateOrUpdateHubTicketService.ts b/backend/src/services/HubServices/CreateOrUpdateHubTicketService.ts new file mode 100644 index 0000000..cd7e908 --- /dev/null +++ b/backend/src/services/HubServices/CreateOrUpdateHubTicketService.ts @@ -0,0 +1,92 @@ +import { Op } from "sequelize"; +import Ticket from "../../models/Ticket"; +import Whatsapp from "../../models/Whatsapp"; +import { IContent } from "./HubMessageListener"; +import { getIO } from "../../libs/socket"; + +interface TicketData { + contactId: number; + channel: string; + contents: IContent[]; + connection: Whatsapp; +} + +const CreateOrUpdateTicketService = async ( + ticketData: TicketData +): Promise => { + + const { contactId, channel, contents, connection } = ticketData; + const io = getIO(); + + const ticketExists = await Ticket.findOne({ + where: { + contactId, + channel, + whatsappId: connection.id, + } + }); + + if (ticketExists) { + + let newStatus = ticketExists.status; + let newQueueId = ticketExists.queueId; + + if (ticketExists.status === "closed") { + newStatus = "pending"; + } + + await ticketExists.update({ + lastMessage: contents[0].text, + status: newStatus, + queueId: newQueueId + }); + + await ticketExists.reload({ + include: [ + { + association: "contact" + }, + { + association: "user" + }, + { + association: "queue" + }, + { + association: "tags" + }, + { + association: "whatsapp" + } + ] + }); + + return ticketExists; + } + + const newTicket = await Ticket.create({ + status: "pending", + channel, + lastMessage: contents[0].text, + contactId, + whatsappId: connection.id + }); + + await newTicket.reload({ + include: [ + { + association: "contact" + }, + { + association: "user" + }, + { + association: "whatsapp" + } + ] + }); + + return newTicket; +}; + +export default CreateOrUpdateTicketService; \ No newline at end of file diff --git a/backend/src/services/HubServices/FindOrCreateHubContactService.ts b/backend/src/services/HubServices/FindOrCreateHubContactService.ts new file mode 100644 index 0000000..10cc7b3 --- /dev/null +++ b/backend/src/services/HubServices/FindOrCreateHubContactService.ts @@ -0,0 +1,69 @@ +import Contact from "../../models/Contact"; +import Whatsapp from "../../models/Whatsapp"; + +interface HubContact { + name: string; + firstName: string; + lastName: string; + picture: string; + from: string; + whatsapp?: Whatsapp | null; // Definindo como opcional e podendo ser null + channel: string; + companyId: number; +} + +const FindOrCreateContactService = async ( + contact: HubContact +): Promise => { + const { name, picture, firstName, lastName, from, channel, companyId, whatsapp } = contact; + + console.log('contact', contact) + let numberFb + let numberIg + let contactExists + + if(channel === 'facebook'){ + numberFb = from + contactExists = await Contact.findOne({ + where: { + messengerId: from, + } + }); + } + + if(channel === 'instagram'){ + numberIg = from + contactExists = await Contact.findOne({ + where: { + instagramId: from + } + }); + } + + // Se o contato já existir, apenas atualizamos as informações + if (contactExists) { + await contactExists.update({ + name: name || firstName || 'Name Unavailable', + firstName, + lastName, + profilePicUrl: picture, + whatsappId: whatsapp ? whatsapp.id : null // Verificando se o whatsapp é passado corretamente + }); + return contactExists; + } + + // Se o contato não existir, criamos um novo + const newContact = await Contact.create({ + name: name || firstName || 'Name Unavailable', + number: null, // Como você está criando o contato via Instagram ou Facebook, número pode ser null + profilePicUrl: picture, + messengerId: numberFb || null, + instagramId: numberIg || null, + companyId: companyId, + whatsappId: whatsapp ? whatsapp.id : null // Atribuindo whatsappId ao novo contato, se disponível + }); + + return newContact; +}; + +export default FindOrCreateContactService; \ No newline at end of file diff --git a/backend/src/services/HubServices/HubMessageListener.ts b/backend/src/services/HubServices/HubMessageListener.ts new file mode 100644 index 0000000..c3182d2 --- /dev/null +++ b/backend/src/services/HubServices/HubMessageListener.ts @@ -0,0 +1,230 @@ +import Ticket from "../../models/Ticket"; +import User from "../../models/User"; +import Whatsapp from "../../models/Whatsapp"; +import { downloadFiles } from "../../helpers/downloadHubFiles"; +import CreateMessageService from "./CreateHubMessageService"; +/*import CreateOrUpdateTicketService from "./CreateOrUpdateHubTicketService";*/ +import FindOrCreateContactService from "./FindOrCreateHubContactService"; +import { UpdateMessageAck } from "./UpdateMessageHubAck"; +import FindOrCreateTicketService from "../TicketServices/FindOrCreateTicketService"; +import { getIO } from "../../libs/socket"; + +export interface HubInMessage { + type: "MESSAGE"; + id: string; + timestamp: string; + subscriptionId: string; + channel: "telegram" | "whatsapp" | "facebook" | "instagram" | "sms" | "email"; + direction: "IN"; + message: { + id: string; + from: string; + to: string; + direction: "IN"; + channel: + | "telegram" + | "whatsapp" + | "facebook" + | "instagram" + | "sms" + | "email"; + visitor: { + name: string; + firstName: string; + lastName: string; + picture: string; + }; + contents: IContent[]; + timestamp: string; + }; +} + +export interface IContent { + type: "text" | "image" | "audio" | "video" | "file" | "location"; + text?: string; + url?: string; + fileUrl?: string; + latitude?: number; + longitude?: number; + filename?: string; + fileSize?: number; + fileMimeType?: string; +} + +export interface HubConfirmationSentMessage { + type: "MESSAGE_STATUS"; + timestamp: string; + subscriptionId: string; + channel: "telegram" | "whatsapp" | "facebook" | "instagram" | "sms" | "email"; + messageId: string; + contentIndex: number; + messageStatus: { + timestamp: string; + code: "SENT" | "REJECTED"; + description: string; + }; +} + +const verifySentMessageStatus = (message: HubConfirmationSentMessage) => { + const { + messageStatus: { code } + } = message; + + const isMessageSent = code === "SENT"; + + if (isMessageSent) { + return true; + } + + return false; +}; + +const HubMessageListener = async ( + message: any | HubInMessage | HubConfirmationSentMessage, + whatsapp: Whatsapp, + medias: Express.Multer.File[] +) => { + console.log("HubMessageListener", message); + console.log("contents", message.message.contents); + + // Se a mensagem for enviada de fora do sistema (OUT), ignoramos + const ignoreEvent = message.direction === "OUT"; + if (ignoreEvent) { + return; + } + + const isMessageFromMe = message.type === "MESSAGE_STATUS"; + + if (isMessageFromMe) { + const isMessageSent = verifySentMessageStatus( + message as HubConfirmationSentMessage + ); + + if (isMessageSent) { + console.log("HubMessageListener: message sent"); + UpdateMessageAck(message.messageId); + } else { + console.log( + "HubMessageListener: message not sent", + message.messageStatus.code, + message.messageStatus.description + ); + } + + return; + } + + // Desestruturando os dados da mensagem recebida + const { + message: { id, from, channel, contents, visitor } + } = message as HubInMessage; + + try { + + const unreadMessages = 1; + + // Passando whatsapp.companyId diretamente para FindOrCreateContactService + const contact = await FindOrCreateContactService({ + ...visitor, + from, + whatsapp, + channel, + companyId: whatsapp.companyId // Passando diretamente + }); + + // Passando o companyId para a função de criação ou atualização do ticket + const ticket = await FindOrCreateTicketService( + contact, + whatsapp.id!, + unreadMessages, + contact.companyId || whatsapp.companyId // Passando o companyId aqui, já atribuído corretamente do contato ou whatsapp + ); + + // Obtendo o companyId corretamente + let companyId = contact.companyId || whatsapp.companyId || ticket.companyId; + + // Se o companyId ainda for indefinido, lança erro + if (!companyId) { + throw new Error("Erro: companyId não encontrado no contato, WhatsApp nem no Ticket."); + console.log("Erro: companyId não encontrado no contato, WhatsApp nem no Ticket."); + } + + + if (contents[0]?.type === "text") { + const messageData = await CreateMessageService({ + id, + contactId: contact.id, + body: contents[0].text || "", + ticketId: ticket.id, + fromMe: false, + companyId: contact.companyId || whatsapp.companyId || ticket.companyId + }); + + await Ticket.update( + { lastMessage: contents[0].text || "" }, + { where: { id: ticket.id } } + ); + + const io = getIO(); + const updatedTicket = await Ticket.findByPk(ticket.id, { include: ["contact"] }); + console.log("Ticket atualizado após mensagem de texto:", updatedTicket); + if (updatedTicket) { + io.to(updatedTicket.status) + .to(ticket.id.toString()) + .emit(`company-${companyId}-ticket`, { + action: "update", + ticket: updatedTicket + }); + console.log("Evento 'ticket' emitido para mensagem de texto:", { + status: updatedTicket.status, + ticketId: ticket.id.toString(), + lastMessage: updatedTicket.lastMessage + }); + } +} else if (contents[0]?.fileUrl) { + //const media = await downloadFiles(contents[0].fileUrl, companyId); + + const media = await downloadFiles(contents[0].fileUrl, companyId, contents[0].type); + + if (typeof media.mimeType === "string") { + const messageData = await CreateMessageService({ + id, + contactId: contact.id, + body: contents[0].text || "", + ticketId: ticket.id, + fromMe: false, + companyId: contact.companyId || whatsapp.companyId || ticket.companyId, + fileName: `${media.filename}`, + mediaType: media.mimeType.split("/")[0], + originalName: media.originalname + }); + + await Ticket.update( + { lastMessage: contents[0].text || media.originalname }, + { where: { id: ticket.id } } + ); + + const io = getIO(); + const updatedTicket = await Ticket.findByPk(ticket.id, { include: ["contact"] }); + console.log("Ticket atualizado após mensagem com arquivo:", updatedTicket); + if (updatedTicket) { + io.to(updatedTicket.status) + .to(ticket.id.toString()) + .emit(`company-${companyId}-ticket`, { + action: "update", + ticket: updatedTicket + }); + console.log("Evento 'ticket' emitido para mensagem com arquivo:", { + status: updatedTicket.status, + ticketId: ticket.id.toString(), + lastMessage: updatedTicket.lastMessage + }); + } + } +} + } catch (error: any) { + console.log(error); + } +}; + +export default HubMessageListener; \ No newline at end of file diff --git a/backend/src/services/HubServices/ListHubChannels.ts b/backend/src/services/HubServices/ListHubChannels.ts new file mode 100644 index 0000000..3daba98 --- /dev/null +++ b/backend/src/services/HubServices/ListHubChannels.ts @@ -0,0 +1,23 @@ +import { showHubToken } from "../../helpers/showHubToken"; +const { Client } = require("notificamehubsdk"); +require("dotenv").config(); + +const ListChannels = async () => { + try { + const notificameHubToken = await showHubToken(); + + if (!notificameHubToken) { + throw new Error("NOTIFICAMEHUB_TOKEN_NOT_FOUND"); + } + + const client = new Client(notificameHubToken); + + const response = await client.listChannels(); + console.log("Response:", response); + return response; + } catch (error) { + throw new Error('Error'); + } +}; + +export default ListChannels; \ No newline at end of file diff --git a/backend/src/services/HubServices/SendMediaMessageHubService.ts b/backend/src/services/HubServices/SendMediaMessageHubService.ts new file mode 100644 index 0000000..e09bfca --- /dev/null +++ b/backend/src/services/HubServices/SendMediaMessageHubService.ts @@ -0,0 +1,172 @@ +require("dotenv").config(); +const { Client, FileContent } = require("notificamehubsdk"); +const ffmpeg = require("fluent-ffmpeg"); +import Contact from "../../models/Contact"; +import Ticket from "../../models/Ticket"; +import CreateMessageService from "./CreateHubMessageService"; +import { showHubToken } from "../../helpers/showHubToken"; +import { convertMp3ToMp4 } from "../../helpers/ConvertMp3ToMp4"; +import * as fs from "fs"; +import { join } from "path"; + +export const SendMediaMessageService = async ( + media: Express.Multer.File, + message: string, + ticketId: number, + contact: Contact, + connection: any, + companyIdOld: number +) => { + const ticket = await Ticket.findOne({ where: { id: ticketId } }); + if (!ticket) { + throw new Error("Ticket não encontrado"); + } + + const companyId = ticket.companyId; + const notificameHubToken = await showHubToken(); + const client = new Client(notificameHubToken); + + let channelClient; + let contactNumber; + let type; + let mediaUrl; + + if (contact.messengerId && !contact.instagramId) { + contactNumber = contact.messengerId; + type = "facebook"; + channelClient = client.setChannel(type); + } + if (!contact.messengerId && contact.instagramId) { + contactNumber = contact.instagramId; + type = "instagram"; + channelClient = client.setChannel(type); + } + + message = message.replace(/\n/g, " "); + const backendUrl = `${process.env.BACKEND_URL}`; + const filename = encodeURIComponent(media.filename); + mediaUrl = `${backendUrl}/public/company${companyId}/${filename}`; + + // Função para converter vídeo MP4 para formato compatível + const convertVideoToCompatibleFormat = async (inputPath: string, destination: string) => { + const outputFilename = `${Date.now()}.mp4`; + const outputPath = join(destination, outputFilename); + + await new Promise((resolve, reject) => { + ffmpeg(inputPath) + .output(outputPath) + .videoCodec("libx264") // H.264 + .audioCodec("aac") // AAC + .outputOptions([ + "-profile:v baseline", // Perfil Baseline para compatibilidade + "-level 3.0", // Nível 3.0 + "-movflags +faststart" // Metadados no início + ]) + .size("854x480") + .on("end", resolve) + .on("error", reject) + .run(); + }); + + return outputFilename; + }; + + // Ajuste para vídeos MP4 (Facebook e Instagram) + if (media.mimetype.includes("video") && (type === "facebook" || type === "instagram")) { + try { + const inputPath = media.path; + const convertedFilename = await convertVideoToCompatibleFormat(inputPath, media.destination); + media.filename = convertedFilename; + mediaUrl = `${backendUrl}/public/company${companyId}/${convertedFilename}`; + media.originalname = convertedFilename; + media.mimetype = "video"; // Define como "video" para ambos + } catch (error) { + console.error(`Erro ao converter vídeo para ${type}:`, error); + } + } else if (media.mimetype.includes("image")) { + if (type === "telegram") { + media.mimetype = "photo"; + } else { + media.mimetype = "image"; + } + } else if ( + (type === "telegram" || type === "facebook") && + media.mimetype.includes("audio") + ) { + media.mimetype = "audio"; + } else if (type === "telegram" || type === "facebook") { + media.mimetype = "file"; + } + + // Conversão de MP3 para Instagram (mantida) + if (media.originalname.includes(".mp3") && type === "instagram") { + const inputPath = media.path; + const outputMP4Path = `${media.destination}/${media.filename.split(".")[0]}.mp4`; + try { + await convertMp3ToMp4(inputPath, outputMP4Path); + media.filename = outputMP4Path.split("/").pop() ?? "default.mp4"; + mediaUrl = `${backendUrl}/public/company${companyId}/${media.filename}`; + media.originalname = media.filename; + media.mimetype = "audio"; + } catch (e) { + console.error("Erro ao converter MP3 para Instagram:", e); + } + } + + // Para MP3 no Facebook (mantida) + if (media.originalname.includes(".mp3") && type === "facebook") { + mediaUrl = `${backendUrl}/public/company${companyId}/${media.filename}`; + media.originalname = media.filename; + media.mimetype = "audio"; + } + + const content = new FileContent( + mediaUrl, + media.mimetype, + media.originalname, + media.originalname + ); + + console.log({ + token: connection.qrcode, + number: contactNumber, + content, + message, + companyId + }); + + try { + let response = await channelClient.sendMessage( + connection.qrcode, + contactNumber, + content + ); + console.log("response:", response); + + let data: any; + try { + const jsonStart = response.indexOf("{"); + const jsonResponse = response.substring(jsonStart); + data = JSON.parse(jsonResponse); + } catch (error) { + data = response; + } + + const newMessage = await CreateMessageService({ + id: data.id, + contactId: contact.id, + companyId, + body: message, + ticketId, + fromMe: true, + fileName: `${media.filename}`, + mediaType: media.mimetype.split("/")[0], + originalName: media.originalname + }); + + return newMessage; + } catch (error) { + console.log("Error:", error); + throw error; + } +}; \ No newline at end of file diff --git a/backend/src/services/HubServices/SendTextMessageHubService.ts b/backend/src/services/HubServices/SendTextMessageHubService.ts new file mode 100644 index 0000000..843e976 --- /dev/null +++ b/backend/src/services/HubServices/SendTextMessageHubService.ts @@ -0,0 +1,125 @@ +require("dotenv").config(); +const { Client, TextContent } = require("notificamehubsdk"); +import Contact from "../../models/Contact"; +import Ticket from "../../models/Ticket"; +import CreateMessageService from "./CreateHubMessageService"; +import { showHubToken } from "../../helpers/showHubToken"; +import { getIO } from "../../libs/socket"; + +export const SendTextMessageService = async ( + message: string, + ticketId: number, + contact: Contact, + connection: any, + companyIdOld: number //Apenas para completar a quantidade de argumentos +) => { + + // Buscar o ticket para obter o companyId + const ticket = await Ticket.findOne({ where: { id: ticketId } }); + + if (!ticket) { + throw new Error("Ticket não encontrado"); + } + + const companyId = ticket.companyId; // Agora temos o companyId + + const notificameHubToken = await showHubToken(); + + const client = new Client(notificameHubToken); + + let channelClient; + + message = message.replace(/\n/g, " "); + + const content = new TextContent(message); + + let contactNumber; + + if(contact.messengerId && !contact.instagramId){ + contactNumber = contact.messengerId + channelClient = client.setChannel('facebook'); + } + if(!contact.messengerId && contact.instagramId){ + contactNumber = contact.instagramId + channelClient = client.setChannel('instagram'); + } + + try { + + console.log({ + token: connection.qrcode, + number: contactNumber, + content, + message, + companyId + }); + + let response = await channelClient.sendMessage( + connection.qrcode, + contactNumber, + content + ); + + console.log("response:", response); + + let data: any; + + try { + const jsonStart = response.indexOf("{"); + const jsonResponse = response.substring(jsonStart); + data = JSON.parse(jsonResponse); + } catch (error) { + data = response; + } + +const newMessage = await CreateMessageService({ + id: data.id, + contactId: contact.id, + companyId, + body: message, + ticketId, + fromMe: true +}); + +await Ticket.update( + { lastMessage: message }, + { where: { id: ticketId } } +); + +const io = getIO(); +const updatedTicket = await Ticket.findByPk(ticketId, { include: ["contact"] }); +console.log("Ticket atualizado após envio do atendente:", updatedTicket); +if (updatedTicket) { + io.to(updatedTicket.status) + .to(ticketId.toString()) + .emit("message", { + action: "create", + message: newMessage, + ticket: updatedTicket + }); + console.log("Evento 'message' emitido para envio:", { + status: updatedTicket.status, + ticketId: ticketId.toString(), + lastMessage: updatedTicket.lastMessage + }); + + io.to(updatedTicket.status) + .to(ticketId.toString()) + .emit(`company-${companyId}-ticket`, { + action: "update", + ticket: updatedTicket + }); + console.log("Evento 'ticket' emitido para envio:", { + status: updatedTicket.status, + ticketId: ticketId.toString(), + lastMessage: updatedTicket.lastMessage + }); +} + +return newMessage; + + + } catch (error) { + console.log("Error:", error); + } +}; \ No newline at end of file diff --git a/backend/src/services/HubServices/UpdateMessageHubAck.ts b/backend/src/services/HubServices/UpdateMessageHubAck.ts new file mode 100644 index 0000000..8199e63 --- /dev/null +++ b/backend/src/services/HubServices/UpdateMessageHubAck.ts @@ -0,0 +1,17 @@ +import Message from "../../models/Message"; + +export const UpdateMessageAck = async (messageId: string): Promise => { + const message = await Message.findOne({ + where: { + id: messageId + } + }); + + if (!message) { + return; + } + + await message.update({ + ack: 3 + }); +}; \ No newline at end of file diff --git a/backend/src/services/InvoicesService/FindAllInvoiceService.ts b/backend/src/services/InvoicesService/FindAllInvoiceService.ts new file mode 100644 index 0000000..47d73cb --- /dev/null +++ b/backend/src/services/InvoicesService/FindAllInvoiceService.ts @@ -0,0 +1,17 @@ +import Invoices from "../../models/Invoices"; + +interface Request { + companyId: number; +} + +const FindAllPlanService = async (companyId: number): Promise => { + const invoice = await Invoices.findAll({ + where: { + companyId + }, + order: [["id", "ASC"]] + }); + return invoice; +}; + +export default FindAllPlanService; diff --git a/backend/src/services/InvoicesService/ListInvoicesServices.ts b/backend/src/services/InvoicesService/ListInvoicesServices.ts new file mode 100644 index 0000000..5b9faff --- /dev/null +++ b/backend/src/services/InvoicesService/ListInvoicesServices.ts @@ -0,0 +1,49 @@ +import { Sequelize, Op } from "sequelize"; +import Invoices from "../../models/Invoices"; + +interface Request { + searchParam?: string; + pageNumber?: string; +} + +interface Response { + invoices: Invoices[]; + count: number; + hasMore: boolean; +} + +const ListInvoicesServices = async ({ + searchParam = "", + pageNumber = "1" +}: Request): Promise => { + const whereCondition = { + [Op.or]: [ + { + name: Sequelize.where( + Sequelize.fn("LOWER", Sequelize.col("detail")), + "LIKE", + `%${searchParam.toLowerCase().trim()}%` + ) + } + ] + }; + const limit = 20; + const offset = limit * (+pageNumber - 1); + + const { count, rows: invoices } = await Invoices.findAndCountAll({ + where: whereCondition, + limit, + offset, + order: [["id", "ASC"]] + }); + + const hasMore = count > offset + invoices.length; + + return { + invoices, + count, + hasMore + }; +}; + +export default ListInvoicesServices; diff --git a/backend/src/services/InvoicesService/ShowInvoiceService.ts b/backend/src/services/InvoicesService/ShowInvoiceService.ts new file mode 100644 index 0000000..a0409c7 --- /dev/null +++ b/backend/src/services/InvoicesService/ShowInvoiceService.ts @@ -0,0 +1,14 @@ +import Invoice from "../../models/Invoices"; +import AppError from "../../errors/AppError"; + +const ShowInvoceService = async (Invoiceid: string | number): Promise => { + const invoice = await Invoice.findByPk(Invoiceid); + + if (!invoice) { + throw new AppError("ERR_NO_PLAN_FOUND", 404); + } + + return invoice; +}; + +export default ShowInvoceService; diff --git a/backend/src/services/InvoicesService/UpdateInvoiceService.ts b/backend/src/services/InvoicesService/UpdateInvoiceService.ts new file mode 100644 index 0000000..6ac45e8 --- /dev/null +++ b/backend/src/services/InvoicesService/UpdateInvoiceService.ts @@ -0,0 +1,25 @@ +import AppError from "../../errors/AppError"; +import Invoice from "../../models/Invoices"; + +interface InvoiceData { + status: string; + id?: number | string; +} + +const UpdateInvoiceService = async (InvoiceData: InvoiceData): Promise => { + const { id, status } = InvoiceData; + + const invoice = await Invoice.findByPk(id); + + if (!invoice) { + throw new AppError("ERR_NO_PLAN_FOUND", 404); + } + + await invoice.update({ + status, + }); + + return invoice; +}; + +export default UpdateInvoiceService; diff --git a/backend/src/services/MessageServices/CreateMessageService.ts b/backend/src/services/MessageServices/CreateMessageService.ts new file mode 100644 index 0000000..015e007 --- /dev/null +++ b/backend/src/services/MessageServices/CreateMessageService.ts @@ -0,0 +1,78 @@ +import { getIO } from "../../libs/socket"; +import Message from "../../models/Message"; +import Ticket from "../../models/Ticket"; +import Whatsapp from "../../models/Whatsapp"; + +interface MessageData { + id: string; + ticketId: number; + body: string; + contactId?: number; + fromMe?: boolean; + read?: boolean; + mediaType?: string; + mediaUrl?: string; + ack?: number; + queueId?: number; + isForwarded?: boolean; +} +interface Request { + messageData: MessageData; + companyId: number; +} + +const CreateMessageService = async ({ + messageData, + companyId +}: Request): Promise => { + await Message.upsert({ ...messageData, companyId }); + + const message = await Message.findByPk(messageData.id, { + include: [ + "contact", + { + model: Ticket, + as: "ticket", + include: [ + "contact", + "queue", + { + model: Whatsapp, + as: "whatsapp", + attributes: ["name"] + } + ] + }, + { + model: Message, + as: "quotedMsg", + include: ["contact"] + } + ] + }); + + if (message.ticket.queueId !== null && message.queueId === null) { + await message.update({ queueId: message.ticket.queueId }); + } + + if (!message) { + throw new Error("ERR_CREATING_MESSAGE"); + } + + const io = getIO(); + io.to(message.ticketId.toString()) + .to(`company-${companyId}-${message.ticket.status}`) + .to(`company-${companyId}-notification`) + .to(`queue-${message.ticket.queueId}-${message.ticket.status}`) + .to(`queue-${message.ticket.queueId}-notification`) + .emit(`company-${companyId}-appMessage`, { + action: "create", + message, + ticket: message.ticket, + contact: message.ticket.contact + }); + + return message; +}; + +export default CreateMessageService; diff --git a/backend/src/services/MessageServices/GetMessagesService.ts b/backend/src/services/MessageServices/GetMessagesService.ts new file mode 100644 index 0000000..b33c014 --- /dev/null +++ b/backend/src/services/MessageServices/GetMessagesService.ts @@ -0,0 +1,20 @@ +import AppError from "../../errors/AppError"; +import Message from "../../models/Message"; + +interface Request { + id: string; +} + +const GetMessageService = async ({ id }: Request): Promise => { + const messageExists = await Message.findOne({ + where: { id } + }); + + if (!messageExists) { + throw new AppError("MESSAGE_NOT_FIND"); + } + + return messageExists; +}; + +export default GetMessageService; diff --git a/backend/src/services/MessageServices/ListMessagesService.ts b/backend/src/services/MessageServices/ListMessagesService.ts new file mode 100644 index 0000000..8cec516 --- /dev/null +++ b/backend/src/services/MessageServices/ListMessagesService.ts @@ -0,0 +1,84 @@ +import { FindOptions } from "sequelize/types"; +import { Op } from "sequelize"; +import AppError from "../../errors/AppError"; +import Message from "../../models/Message"; +import Ticket from "../../models/Ticket"; +import ShowTicketService from "../TicketServices/ShowTicketService"; +import Queue from "../../models/Queue"; + +interface Request { + ticketId: string; + companyId: number; + pageNumber?: string; + queues?: number[]; +} + +interface Response { + messages: Message[]; + ticket: Ticket; + count: number; + hasMore: boolean; +} + +const ListMessagesService = async ({ + pageNumber = "1", + ticketId, + companyId, + queues = [] +}: Request): Promise => { + const ticket = await ShowTicketService(ticketId, companyId); + + if (!ticket) { + throw new AppError("ERR_NO_TICKET_FOUND", 404); + } + + // await setMessagesAsRead(ticket); + const limit = 20; + const offset = limit * (+pageNumber - 1); + + const options: FindOptions = { + where: { + ticketId, + companyId + } + }; + + if (queues.length > 0) { + options.where["queueId"] = { + [Op.or]: { + [Op.in]: queues, + [Op.eq]: null + } + }; + } + + const { count, rows: messages } = await Message.findAndCountAll({ + ...options, + limit, + include: [ + "contact", + { + model: Message, + as: "quotedMsg", + include: ["contact"] + }, + { + model: Queue, + as: "queue" + } + ], + offset, + order: [["createdAt", "DESC"]] + }); + + const hasMore = count > offset + messages.length; + + return { + messages: messages.reverse(), + ticket, + count, + hasMore + }; +}; + +export default ListMessagesService; diff --git a/backend/src/services/MessageServices/ShowMessageService.ts b/backend/src/services/MessageServices/ShowMessageService.ts new file mode 100644 index 0000000..d54aca9 --- /dev/null +++ b/backend/src/services/MessageServices/ShowMessageService.ts @@ -0,0 +1,27 @@ +import sequelize from "../../database"; +import Message from "../../models/Message"; +import Ticket from "../../models/Ticket"; +import Whatsapp from "../../models/Whatsapp"; + +const ShowMessageService = async (messageId: string) => { + const message = await sequelize.query(`select * from "Messages" where id = '${messageId}'`, { + model: Message, + mapToModel: true + }); + if (message.length > 0) { + return message[0] as unknown as Message; + } + return undefined; +} + +export const GetWhatsAppFromMessage = async (message: Message): Promise => { + const ticketId = message.ticketId; + const ticket = await Ticket.findByPk(ticketId); + if (!ticket) { + return null; + } + return ticket.whatsappId; +} + + +export default ShowMessageService; diff --git a/backend/src/services/PlanService/CreatePlanService.ts b/backend/src/services/PlanService/CreatePlanService.ts new file mode 100644 index 0000000..704b339 --- /dev/null +++ b/backend/src/services/PlanService/CreatePlanService.ts @@ -0,0 +1,54 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import Plan from "../../models/Plan"; + +interface PlanData { + name: string; + users: number; + connections: number; + queues: number; + value: number; + useCampaigns?: boolean; + useSchedules?: boolean; + useInternalChat?: boolean; + useExternalApi?: boolean; + useKanban?: boolean; + useOpenAi?: boolean; + useIntegrations?: boolean; +} + +const CreatePlanService = async (planData: PlanData): Promise => { + const { name } = planData; + + const planSchema = Yup.object().shape({ + name: Yup.string() + .min(2, "ERR_PLAN_INVALID_NAME") + .required("ERR_PLAN_INVALID_NAME") + .test( + "Check-unique-name", + "ERR_PLAN_NAME_ALREADY_EXISTS", + async value => { + if (value) { + const planWithSameName = await Plan.findOne({ + where: { name: value } + }); + + return !planWithSameName; + } + return false; + } + ) + }); + + try { + await planSchema.validate({ name }); + } catch (err) { + throw new AppError(err.message); + } + + const plan = await Plan.create(planData); + + return plan; +}; + +export default CreatePlanService; diff --git a/backend/src/services/PlanService/DeletePlanService.ts b/backend/src/services/PlanService/DeletePlanService.ts new file mode 100644 index 0000000..47764b9 --- /dev/null +++ b/backend/src/services/PlanService/DeletePlanService.ts @@ -0,0 +1,16 @@ +import Plan from "../../models/Plan"; +import AppError from "../../errors/AppError"; + +const DeletePlanService = async (id: string): Promise => { + const plan = await Plan.findOne({ + where: { id } + }); + + if (!plan) { + throw new AppError("ERR_NO_PLAN_FOUND", 404); + } + + await plan.destroy(); +}; + +export default DeletePlanService; diff --git a/backend/src/services/PlanService/FindAllPlanService.ts b/backend/src/services/PlanService/FindAllPlanService.ts new file mode 100644 index 0000000..1aa20e4 --- /dev/null +++ b/backend/src/services/PlanService/FindAllPlanService.ts @@ -0,0 +1,10 @@ +import Plan from "../../models/Plan"; + +const FindAllPlanService = async (): Promise => { + const plan = await Plan.findAll({ + order: [["name", "ASC"]] + }); + return plan; +}; + +export default FindAllPlanService; diff --git a/backend/src/services/PlanService/FindAllPlanServiceRegister.ts b/backend/src/services/PlanService/FindAllPlanServiceRegister.ts new file mode 100644 index 0000000..f1aeb60 --- /dev/null +++ b/backend/src/services/PlanService/FindAllPlanServiceRegister.ts @@ -0,0 +1,13 @@ +import Plan from "../../models/Plan"; + +const FindAllPlanServiceRegister = async (): Promise => { + const plans = await Plan.findAll({ + where: { + useInternal: true + }, + order: [["name", "ASC"]] + }); + return plans; +}; + +export default FindAllPlanServiceRegister; diff --git a/backend/src/services/PlanService/ListPlansService.ts b/backend/src/services/PlanService/ListPlansService.ts new file mode 100644 index 0000000..e244c91 --- /dev/null +++ b/backend/src/services/PlanService/ListPlansService.ts @@ -0,0 +1,49 @@ +import { Sequelize, Op } from "sequelize"; +import Plan from "../../models/Plan"; + +interface Request { + searchParam?: string; + pageNumber?: string; +} + +interface Response { + plans: Plan[]; + count: number; + hasMore: boolean; +} + +const ListPlansService = async ({ + searchParam = "", + pageNumber = "1" +}: Request): Promise => { + const whereCondition = { + [Op.or]: [ + { + name: Sequelize.where( + Sequelize.fn("LOWER", Sequelize.col("name")), + "LIKE", + `%${searchParam.toLowerCase().trim()}%` + ) + } + ] + }; + const limit = 20; + const offset = limit * (+pageNumber - 1); + + const { count, rows: plans } = await Plan.findAndCountAll({ + where: whereCondition, + limit, + offset, + order: [["name", "ASC"]] + }); + + const hasMore = count > offset + plans.length; + + return { + plans, + count, + hasMore + }; +}; + +export default ListPlansService; diff --git a/backend/src/services/PlanService/ShowPlanService.ts b/backend/src/services/PlanService/ShowPlanService.ts new file mode 100644 index 0000000..96f9388 --- /dev/null +++ b/backend/src/services/PlanService/ShowPlanService.ts @@ -0,0 +1,14 @@ +import Plan from "../../models/Plan"; +import AppError from "../../errors/AppError"; + +const ShowPlanService = async (id: string | number): Promise => { + const plan = await Plan.findByPk(id); + + if (!plan) { + throw new AppError("ERR_NO_PLAN_FOUND", 404); + } + + return plan; +}; + +export default ShowPlanService; diff --git a/backend/src/services/PlanService/UpdatePlanService.ts b/backend/src/services/PlanService/UpdatePlanService.ts new file mode 100644 index 0000000..7cfeb35 --- /dev/null +++ b/backend/src/services/PlanService/UpdatePlanService.ts @@ -0,0 +1,34 @@ +import AppError from "../../errors/AppError"; +import Plan from "../../models/Plan"; + +interface PlanData { + name: string; + id?: number | string; + users?: number; + connections?: number; + queues?: number; + value?: number; + useCampaigns?: boolean; + useSchedules?: boolean; + useInternalChat?: boolean; + useExternalApi?: boolean; + useKanban?: boolean; + useOpenAi?: boolean; + useIntegrations?: boolean; +} + +const UpdatePlanService = async (planData: PlanData): Promise => { + const { id, name, users, connections, queues, value } = planData; + + const plan = await Plan.findByPk(id); + + if (!plan) { + throw new AppError("ERR_NO_PLAN_FOUND", 404); + } + + await plan.update(planData); + + return plan; +}; + +export default UpdatePlanService; diff --git a/backend/src/services/PromptServices/CreatePromptService.ts b/backend/src/services/PromptServices/CreatePromptService.ts new file mode 100644 index 0000000..ccf8029 --- /dev/null +++ b/backend/src/services/PromptServices/CreatePromptService.ts @@ -0,0 +1,47 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import Prompt from "../../models/Prompt"; +import ShowPromptService from "./ShowPromptService"; + +interface PromptData { + name: string; + apiKey: string; + prompt: string; + maxTokens?: number; + temperature?: number; + promptTokens?: number; + completionTokens?: number; + totalTokens?: number; + queueId?: number; + maxMessages?: number; + companyId: string | number; + voice?: string; + voiceKey?: string; + voiceRegion?: string; +} + +const CreatePromptService = async (promptData: PromptData): Promise => { + const { name, apiKey, prompt, queueId,maxMessages,companyId } = promptData; + + const promptSchema = Yup.object().shape({ + name: Yup.string().required("ERR_PROMPT_NAME_INVALID"), + prompt: Yup.string().required("ERR_PROMPT_INTELLIGENCE_INVALID"), + apiKey: Yup.string().required("ERR_PROMPT_APIKEY_INVALID"), + queueId: Yup.number().required("ERR_PROMPT_QUEUEID_INVALID"), + maxMessages: Yup.number().required("ERR_PROMPT_MAX_MESSAGES_INVALID"), + companyId: Yup.number().required("ERR_PROMPT_companyId_INVALID") + }); + + try { + await promptSchema.validate({ name, apiKey, prompt, queueId,maxMessages,companyId }); + } catch (err) { + throw new AppError(`${JSON.stringify(err, undefined, 2)}`); + } + + let promptTable = await Prompt.create(promptData); + promptTable = await ShowPromptService({ promptId: promptTable.id, companyId }); + + return promptTable; +}; + +export default CreatePromptService; diff --git a/backend/src/services/PromptServices/DeletePromptService.ts b/backend/src/services/PromptServices/DeletePromptService.ts new file mode 100644 index 0000000..9fc04d6 --- /dev/null +++ b/backend/src/services/PromptServices/DeletePromptService.ts @@ -0,0 +1,9 @@ +import ShowPromptService from "./ShowPromptService"; + +const DeletePromptService = async (promptId: number | string, companyId: number | string): Promise => { + const prompt = await ShowPromptService({ promptId, companyId }); + + await prompt.destroy(); +}; + +export default DeletePromptService; diff --git a/backend/src/services/PromptServices/ListPromptsService.ts b/backend/src/services/PromptServices/ListPromptsService.ts new file mode 100644 index 0000000..8b0540c --- /dev/null +++ b/backend/src/services/PromptServices/ListPromptsService.ts @@ -0,0 +1,56 @@ +import { Op } from "sequelize"; +import Prompt from "../../models/Prompt"; +import Queue from "../../models/Queue"; + +interface Request { + searchParam?: string; + pageNumber?: string | number; + companyId: string | number; +} + +interface Response { + prompts: Prompt[]; + count: number; + hasMore: boolean; +} + +const ListPromptsService = async ({ + searchParam = "", + pageNumber = "1", + companyId +}: Request): Promise => { + let whereCondition = {}; + const limit = 20; + const offset = limit * (+pageNumber - 1); + + if (searchParam) { + whereCondition = { + [Op.or]: [ + { name: { [Op.like]: `%${searchParam}%` } } + ] + } + } + + const { count, rows: prompts } = await Prompt.findAndCountAll({ + where: { ...whereCondition, companyId }, + include: [ + { + model: Queue, + as: "queue", + attributes: ["id", "name"] + } + ], + limit, + offset, + order: [["name", "ASC"]], + }); + const hasMore = count > offset + prompts.length; + + return { + prompts, + count, + hasMore + }; +}; + +export default ListPromptsService; diff --git a/backend/src/services/PromptServices/ShowPromptService.ts b/backend/src/services/PromptServices/ShowPromptService.ts new file mode 100644 index 0000000..13424d1 --- /dev/null +++ b/backend/src/services/PromptServices/ShowPromptService.ts @@ -0,0 +1,30 @@ +import AppError from "../../errors/AppError"; +import Prompt from "../../models/Prompt"; +import Queue from "../../models/Queue"; + +interface Data { + promptId: string | number; + companyId: string | number; +} +const ShowPromptService = async ({ promptId, companyId }: Data): Promise => { + + const prompt = await Prompt.findOne({ + where: { + id: promptId, + companyId + }, + include: [ + { + model: Queue, + as: "queue" + } + ] + }); + + if (!prompt) { + throw new AppError("ERR_NO_PROMPT_FOUND", 404); + } + + return prompt; +}; +export default ShowPromptService; diff --git a/backend/src/services/PromptServices/UpdatePromptService.ts b/backend/src/services/PromptServices/UpdatePromptService.ts new file mode 100644 index 0000000..ed70999 --- /dev/null +++ b/backend/src/services/PromptServices/UpdatePromptService.ts @@ -0,0 +1,58 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import Prompt from "../../models/Prompt"; +import ShowPromptService from "./ShowPromptService"; + +interface PromptData { + id?: number; + name: string; + apiKey: string; + prompt: string; + maxTokens?: number; + temperature?: number; + promptTokens?: number; + completionTokens?: number; + totalTokens?: number; + queueId?: number; + maxMessages?: number; + companyId: string | number; + voice?: string; + voiceKey?: string; + voiceRegion?: string; +} + +interface Request { + promptData: PromptData; + promptId: string | number; + companyId: string | number; +} + +const UpdatePromptService = async ({ + promptId, + promptData, + companyId +}: Request): Promise => { + const promptTable = await ShowPromptService({ promptId: promptId, companyId }); + + const promptSchema = Yup.object().shape({ + name: Yup.string().required("ERR_PROMPT_NAME_INVALID"), + prompt: Yup.string().required("ERR_PROMPT_PROMPT_INVALID"), + apiKey: Yup.string().required("ERR_PROMPT_APIKEY_INVALID"), + queueId: Yup.number().required("ERR_PROMPT_QUEUEID_INVALID"), + maxMessages: Yup.number().required("ERR_PROMPT_MAX_MESSAGES_INVALID") + }); + + const { name, apiKey, prompt, maxTokens, temperature, promptTokens, completionTokens, totalTokens, queueId, maxMessages, voice, voiceKey, voiceRegion } = promptData; + + try { + await promptSchema.validate({ name, apiKey, prompt, maxTokens, temperature, promptTokens, completionTokens, totalTokens, queueId, maxMessages }); + } catch (err) { + throw new AppError(`${JSON.stringify(err, undefined, 2)}`); + } + + await promptTable.update({ name, apiKey, prompt, maxTokens, temperature, promptTokens, completionTokens, totalTokens, queueId, maxMessages, voice, voiceKey, voiceRegion }); + await promptTable.reload(); + return promptTable; +}; + +export default UpdatePromptService; diff --git a/backend/src/services/QueueIntegrationServices/CreateQueueIntegrationService.ts b/backend/src/services/QueueIntegrationServices/CreateQueueIntegrationService.ts new file mode 100644 index 0000000..c0f4529 --- /dev/null +++ b/backend/src/services/QueueIntegrationServices/CreateQueueIntegrationService.ts @@ -0,0 +1,86 @@ +import * as Yup from "yup"; + +import AppError from "../../errors/AppError"; +import QueueIntegrations from "../../models/QueueIntegrations"; + + +interface Request { + type: string; + name: string; + projectName: string; + jsonContent: string; + language: string; + urlN8N?: string; + companyId: number; + typebotSlug?: string; + typebotExpires?: number; + typebotKeywordFinish?: string; + typebotUnknownMessage?: string; + typebotDelayMessage?: number; + typebotKeywordRestart?: string; + typebotRestartMessage?: string; +} + +const CreateQueueIntegrationService = async ({ + type, + name, + projectName, + jsonContent, + language, + urlN8N, + companyId, + typebotExpires, + typebotKeywordFinish, + typebotSlug, + typebotUnknownMessage, + typebotDelayMessage, + typebotKeywordRestart, + typebotRestartMessage +}: Request): Promise => { + const schema = Yup.object().shape({ + name: Yup.string() + .required() + .min(2) + .test( + "Check-name", + "This integration name is already used.", + async value => { + if (!value) return false; + const nameExists = await QueueIntegrations.findOne({ + where: { name: value, companyId } + }); + return !nameExists; + } + ) + }); + + try { + await schema.validate({ type, name, projectName, jsonContent, language, urlN8N, companyId }); + } catch (err) { + throw new AppError(err.message); + } + + + const queueIntegration = await QueueIntegrations.create( + { + type, + name, + projectName, + jsonContent, + language, + urlN8N, + companyId, + typebotExpires, + typebotKeywordFinish, + typebotSlug, + typebotUnknownMessage, + typebotDelayMessage, + typebotKeywordRestart, + typebotRestartMessage + } + ); + + return queueIntegration; +}; + +export default CreateQueueIntegrationService; \ No newline at end of file diff --git a/backend/src/services/QueueIntegrationServices/DeleteQueueIntegrationService.ts b/backend/src/services/QueueIntegrationServices/DeleteQueueIntegrationService.ts new file mode 100644 index 0000000..5f9d3ef --- /dev/null +++ b/backend/src/services/QueueIntegrationServices/DeleteQueueIntegrationService.ts @@ -0,0 +1,16 @@ +import QueueIntegrations from "../../models/QueueIntegrations"; +import AppError from "../../errors/AppError"; + +const DeleteQueueIntegrationService = async (id: string): Promise => { + const dialogflow = await QueueIntegrations.findOne({ + where: { id } + }); + + if (!dialogflow) { + throw new AppError("ERR_NO_DIALOG_FOUND", 404); + } + + await dialogflow.destroy(); +}; + +export default DeleteQueueIntegrationService; \ No newline at end of file diff --git a/backend/src/services/QueueIntegrationServices/ListQueueIntegrationService.ts b/backend/src/services/QueueIntegrationServices/ListQueueIntegrationService.ts new file mode 100644 index 0000000..18247a6 --- /dev/null +++ b/backend/src/services/QueueIntegrationServices/ListQueueIntegrationService.ts @@ -0,0 +1,57 @@ +import { Sequelize, Op, Filterable } from "sequelize"; +import QueueIntegrations from "../../models/QueueIntegrations"; + +interface Request { + searchParam?: string; + pageNumber?: string | number; + companyId: number; +} + +interface Response { + queueIntegrations: QueueIntegrations[]; + count: number; + hasMore: boolean; +} + +const ListQueueIntegrationService = async ({ + searchParam = "", + pageNumber = "1", + companyId +}: Request): Promise => { + let whereCondition: Filterable["where"] = { + [Op.or]: [ + { + "$QueueIntegrations.name$": Sequelize.where( + Sequelize.fn("LOWER", Sequelize.col("QueueIntegrations.name")), + "LIKE", + `%${searchParam.toLowerCase()}%` + ) + } + ] + }; + + whereCondition = { + ...whereCondition, + companyId + }; + + const limit = 20; + const offset = limit * (+pageNumber - 1); + + const { count, rows: queueIntegrations } = await QueueIntegrations.findAndCountAll({ + where: whereCondition, + limit, + offset, + order: [["createdAt", "DESC"]], + }); + + const hasMore = count > offset + queueIntegrations.length; + + return { + queueIntegrations, + count, + hasMore + }; +}; + +export default ListQueueIntegrationService; \ No newline at end of file diff --git a/backend/src/services/QueueIntegrationServices/ShowQueueIntegrationService.ts b/backend/src/services/QueueIntegrationServices/ShowQueueIntegrationService.ts new file mode 100644 index 0000000..11d37b1 --- /dev/null +++ b/backend/src/services/QueueIntegrationServices/ShowQueueIntegrationService.ts @@ -0,0 +1,19 @@ +import QueueIntegrations from "../../models/QueueIntegrations"; +import AppError from "../../errors/AppError"; + + +const ShowQueueIntegrationService = async (id: string | number, companyId: number): Promise => { + const integration = await QueueIntegrations.findByPk(id); + + // if (Number(integration?.companyId) !== Number(companyId)) { + // throw new AppError("Não é possível excluir registro de outra empresa"); + // } + + if (!integration) { + throw new AppError("ERR_NO_DIALOG_FOUND", 404); + } + + return integration; +}; + +export default ShowQueueIntegrationService; \ No newline at end of file diff --git a/backend/src/services/QueueIntegrationServices/UpdateQueueIntegrationService.ts b/backend/src/services/QueueIntegrationServices/UpdateQueueIntegrationService.ts new file mode 100644 index 0000000..b973fc8 --- /dev/null +++ b/backend/src/services/QueueIntegrationServices/UpdateQueueIntegrationService.ts @@ -0,0 +1,83 @@ +import * as Yup from "yup"; + +import AppError from "../../errors/AppError"; +import QueueIntegrations from "../../models/QueueIntegrations"; +import ShowIntegrationService from "./ShowQueueIntegrationService"; + +interface IntegrationData { + type?: string; + name?: string; + projectName?: string; + jsonContent?: string; + language?: string; + urlN8N?: string; + typebotSlug?: string; + typebotExpires?: number; + typebotKeywordFinish?: string; + typebotUnknownMessage?: string; + typebotDelayMessage?: number; + typebotKeywordRestart?: string; + typebotRestartMessage?: string; +} + +interface Request { + integrationData: IntegrationData; + integrationId: string; + companyId: number; +} + +const UpdateQueueIntegrationService = async ({ + integrationData, + integrationId, + companyId +}: Request): Promise => { + const schema = Yup.object().shape({ + type: Yup.string().min(2), + name: Yup.string().min(2) + }); + + const { + type, + name, + projectName, + jsonContent, + language, + urlN8N, + typebotExpires, + typebotKeywordFinish, + typebotSlug, + typebotUnknownMessage, + typebotDelayMessage, + typebotKeywordRestart, + typebotRestartMessage + } = integrationData; + + try { + await schema.validate({ type, name, projectName, jsonContent, language, urlN8N }); + } catch (err) { + throw new AppError(err.message); + } + + const integration = await ShowIntegrationService(integrationId, companyId); + + await integration.update({ + type, + name, + projectName, + jsonContent, + language, + urlN8N, + companyId, + typebotExpires, + typebotKeywordFinish, + typebotSlug, + typebotUnknownMessage, + typebotDelayMessage, + typebotKeywordRestart, + typebotRestartMessage + }); + + return integration; +}; + +export default UpdateQueueIntegrationService; \ No newline at end of file diff --git a/backend/src/services/QueueOptionService/CreateService.ts b/backend/src/services/QueueOptionService/CreateService.ts new file mode 100644 index 0000000..6027841 --- /dev/null +++ b/backend/src/services/QueueOptionService/CreateService.ts @@ -0,0 +1,16 @@ +import QueueOption from "../../models/QueueOption"; + +interface QueueOptionData { + queueId: string; + title: string; + option: string; + message?: string; + parentId?: string; +} + +const CreateService = async (queueOptionData: QueueOptionData): Promise => { + const queueOption = await QueueOption.create(queueOptionData); + return queueOption; +}; + +export default CreateService; diff --git a/backend/src/services/QueueOptionService/DeleteService.ts b/backend/src/services/QueueOptionService/DeleteService.ts new file mode 100644 index 0000000..07a506e --- /dev/null +++ b/backend/src/services/QueueOptionService/DeleteService.ts @@ -0,0 +1,9 @@ +import ShowService from "./ShowService"; + +const DeleteService = async (queueOptionId: number | string): Promise => { + const queueOption = await ShowService(queueOptionId); + + await queueOption.destroy(); +}; + +export default DeleteService; diff --git a/backend/src/services/QueueOptionService/ListService.ts b/backend/src/services/QueueOptionService/ListService.ts new file mode 100644 index 0000000..a2cc9b1 --- /dev/null +++ b/backend/src/services/QueueOptionService/ListService.ts @@ -0,0 +1,38 @@ +import { WhereOptions } from "sequelize/types"; +import QueueOption from "../../models/QueueOption"; + +type QueueOptionFilter = { + queueId: string | number; + queueOptionId: string | number; + parentId: string | number | boolean; +}; + +const ListService = async ({ queueId, queueOptionId, parentId }: QueueOptionFilter): Promise => { + + const whereOptions: WhereOptions = {}; + + if (queueId) { + whereOptions.queueId = queueId; + } + + if (queueOptionId) { + whereOptions.id = queueOptionId; + } + + if (parentId == -1) { + whereOptions.parentId = null; + } + + if (parentId > 0) { + whereOptions.parentId = parentId; + } + + const queueOptions = await QueueOption.findAll({ + where: whereOptions, + order: [["id", "ASC"]] + }); + + return queueOptions; +}; + +export default ListService; diff --git a/backend/src/services/QueueOptionService/ShowService.ts b/backend/src/services/QueueOptionService/ShowService.ts new file mode 100644 index 0000000..bbb24a0 --- /dev/null +++ b/backend/src/services/QueueOptionService/ShowService.ts @@ -0,0 +1,26 @@ +import AppError from "../../errors/AppError"; +import QueueOption from "../../models/QueueOption"; + +const ShowService = async (queueOptionId: number | string): Promise => { + const queue = await QueueOption.findOne({ + where: { + id: queueOptionId + }, + include: [ + { + model: QueueOption, + as: 'parent', + where: { parentId: queueOptionId }, + required: false + }, + ] + }); + + if (!queue) { + throw new AppError("ERR_QUEUE_NOT_FOUND"); + } + + return queue; +}; + +export default ShowService; diff --git a/backend/src/services/QueueOptionService/UpdateService.ts b/backend/src/services/QueueOptionService/UpdateService.ts new file mode 100644 index 0000000..f288f80 --- /dev/null +++ b/backend/src/services/QueueOptionService/UpdateService.ts @@ -0,0 +1,24 @@ +import QueueOption from "../../models/QueueOption"; +import ShowService from "./ShowService"; + +interface QueueData { + queueId?: string; + title?: string; + option?: string; + message?: string; + parentId?: string; +} + +const UpdateService = async ( + queueOptionId: number | string, + queueOptionData: QueueData +): Promise => { + + const queueOption = await ShowService(queueOptionId); + + await queueOption.update(queueOptionData); + + return queueOption; +}; + +export default UpdateService; diff --git a/backend/src/services/QueueService/CreateQueueService.ts b/backend/src/services/QueueService/CreateQueueService.ts new file mode 100644 index 0000000..b428c83 --- /dev/null +++ b/backend/src/services/QueueService/CreateQueueService.ts @@ -0,0 +1,94 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import Queue from "../../models/Queue"; +import Company from "../../models/Company"; +import Plan from "../../models/Plan"; + +interface QueueData { + name: string; + color: string; + companyId: number; + greetingMessage?: string; + outOfHoursMessage?: string; + schedules?: any[]; + orderQueue?: number; + integrationId?: number; + promptId?: number; +} + +const CreateQueueService = async (queueData: QueueData): Promise => { + const { color, name, companyId } = queueData; + + const company = await Company.findOne({ + where: { + id: companyId + }, + include: [{ model: Plan, as: "plan" }] + }); + + if (company !== null) { + const queuesCount = await Queue.count({ + where: { + companyId + } + }); + + if (queuesCount >= company.plan.queues) { + throw new AppError(`Número máximo de filas já alcançado: ${queuesCount}`); + } + } + + const queueSchema = Yup.object().shape({ + name: Yup.string() + .min(2, "ERR_QUEUE_INVALID_NAME") + .required("ERR_QUEUE_INVALID_NAME") + .test( + "Check-unique-name", + "ERR_QUEUE_NAME_ALREADY_EXISTS", + async value => { + if (value) { + const queueWithSameName = await Queue.findOne({ + where: { name: value, companyId } + }); + + return !queueWithSameName; + } + return false; + } + ), + color: Yup.string() + .required("ERR_QUEUE_INVALID_COLOR") + .test("Check-color", "ERR_QUEUE_INVALID_COLOR", async value => { + if (value) { + const colorTestRegex = /^#[0-9a-f]{3,6}$/i; + return colorTestRegex.test(value); + } + return false; + }) + .test( + "Check-color-exists", + "ERR_QUEUE_COLOR_ALREADY_EXISTS", + async value => { + if (value) { + const queueWithSameColor = await Queue.findOne({ + where: { color: value, companyId } + }); + return !queueWithSameColor; + } + return false; + } + ) + }); + + try { + await queueSchema.validate({ color, name }); + } catch (err: any) { + throw new AppError(err.message); + } + + const queue = await Queue.create(queueData); + + return queue; +}; + +export default CreateQueueService; diff --git a/backend/src/services/QueueService/DeleteQueueService.ts b/backend/src/services/QueueService/DeleteQueueService.ts new file mode 100644 index 0000000..3a04c3e --- /dev/null +++ b/backend/src/services/QueueService/DeleteQueueService.ts @@ -0,0 +1,12 @@ +import ShowQueueService from "./ShowQueueService"; + +const DeleteQueueService = async ( + queueId: number | string, + companyId: number +): Promise => { + const queue = await ShowQueueService(queueId, companyId); + + await queue.destroy(); +}; + +export default DeleteQueueService; diff --git a/backend/src/services/QueueService/ListQueuesService.ts b/backend/src/services/QueueService/ListQueuesService.ts new file mode 100644 index 0000000..b092209 --- /dev/null +++ b/backend/src/services/QueueService/ListQueuesService.ts @@ -0,0 +1,18 @@ +import Queue from "../../models/Queue"; + +interface Request { + companyId: number; +} + +const ListQueuesService = async ({ companyId }: Request): Promise => { + const queues = await Queue.findAll({ + where: { + companyId + }, + order: [["orderQueue", "ASC"]] + }); + + return queues; +}; + +export default ListQueuesService; diff --git a/backend/src/services/QueueService/ShowQueueService.ts b/backend/src/services/QueueService/ShowQueueService.ts new file mode 100644 index 0000000..3c3329d --- /dev/null +++ b/backend/src/services/QueueService/ShowQueueService.ts @@ -0,0 +1,21 @@ +import AppError from "../../errors/AppError"; +import Queue from "../../models/Queue"; + +const ShowQueueService = async ( + queueId: number | string, + companyId: number +): Promise => { + const queue = await Queue.findByPk(queueId); + + if (queue?.companyId !== companyId) { + throw new AppError("Não é possível consultar registros de outra empresa"); + } + + if (!queue) { + throw new AppError("ERR_QUEUE_NOT_FOUND"); + } + + return queue; +}; + +export default ShowQueueService; diff --git a/backend/src/services/QueueService/UpdateQueueService.ts b/backend/src/services/QueueService/UpdateQueueService.ts new file mode 100644 index 0000000..50028e8 --- /dev/null +++ b/backend/src/services/QueueService/UpdateQueueService.ts @@ -0,0 +1,83 @@ +import { Op } from "sequelize"; +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import Queue from "../../models/Queue"; +import ShowQueueService from "./ShowQueueService"; + +interface QueueData { + name?: string; + color?: string; + greetingMessage?: string; + outOfHoursMessage?: string; + schedules?: any[]; + orderQueue?: number; + integrationId?: number; + promptId?: number; +} + +const UpdateQueueService = async ( + queueId: number | string, + queueData: QueueData, + companyId: number +): Promise => { + const { color, name } = queueData; + + const queueSchema = Yup.object().shape({ + name: Yup.string() + .min(2, "ERR_QUEUE_INVALID_NAME") + .test( + "Check-unique-name", + "ERR_QUEUE_NAME_ALREADY_EXISTS", + async value => { + if (value) { + const queueWithSameName = await Queue.findOne({ + where: { name: value, id: { [Op.ne]: queueId }, companyId } + }); + + return !queueWithSameName; + } + return true; + } + ), + color: Yup.string() + .required("ERR_QUEUE_INVALID_COLOR") + .test("Check-color", "ERR_QUEUE_INVALID_COLOR", async value => { + if (value) { + const colorTestRegex = /^#[0-9a-f]{3,6}$/i; + return colorTestRegex.test(value); + } + return true; + }) + .test( + "Check-color-exists", + "ERR_QUEUE_COLOR_ALREADY_EXISTS", + async value => { + if (value) { + const queueWithSameColor = await Queue.findOne({ + where: { color: value, id: { [Op.ne]: queueId }, companyId } + }); + return !queueWithSameColor; + } + return true; + } + ) + }); + + try { + await queueSchema.validate({ color, name }); + } catch (err: any) { + throw new AppError(err.message); + } + + const queue = await ShowQueueService(queueId, companyId); + + if (queue.companyId !== companyId) { + throw new AppError("Não é permitido alterar registros de outra empresa"); + } + + await queue.update(queueData); + + return queue; +}; + +export default UpdateQueueService; diff --git a/backend/src/services/QuickMessageService/CreateService.ts b/backend/src/services/QuickMessageService/CreateService.ts new file mode 100644 index 0000000..e1e38bf --- /dev/null +++ b/backend/src/services/QuickMessageService/CreateService.ts @@ -0,0 +1,36 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import QuickMessage from "../../models/QuickMessage"; + +interface Data { + shortcode: string; + message: string; + companyId: number | string; + userId: number | string; + geral: boolean; +} + +const CreateService = async (data: Data): Promise => { + const { shortcode, message, geral } = data; + + const ticketnoteSchema = Yup.object().shape({ + shortcode: Yup.string() + .min(3, "ERR_QUICKMESSAGE_INVALID_NAME") + .required("ERR_QUICKMESSAGE_REQUIRED"), + message: Yup.string() + .min(3, "ERR_QUICKMESSAGE_INVALID_NAME") + .required("ERR_QUICKMESSAGE_REQUIRED") + }); + + try { + await ticketnoteSchema.validate({ shortcode, message }); + } catch (err: any) { + throw new AppError(err.message); + } + + const record = await QuickMessage.create(data); + + return record; +}; + +export default CreateService; diff --git a/backend/src/services/QuickMessageService/DeleteService.ts b/backend/src/services/QuickMessageService/DeleteService.ts new file mode 100644 index 0000000..e2d09bf --- /dev/null +++ b/backend/src/services/QuickMessageService/DeleteService.ts @@ -0,0 +1,16 @@ +import QuickMessage from "../../models/QuickMessage"; +import AppError from "../../errors/AppError"; + +const DeleteService = async (id: string): Promise => { + const record = await QuickMessage.findOne({ + where: { id } + }); + + if (!record) { + throw new AppError("ERR_NO_QUICKMESSAGE_FOUND", 404); + } + + await record.destroy(); +}; + +export default DeleteService; diff --git a/backend/src/services/QuickMessageService/FindAllService.ts b/backend/src/services/QuickMessageService/FindAllService.ts new file mode 100644 index 0000000..e461f72 --- /dev/null +++ b/backend/src/services/QuickMessageService/FindAllService.ts @@ -0,0 +1,10 @@ +import QuickMessage from "../../models/QuickMessage"; + +const FindAllService = async (): Promise => { + const records: QuickMessage[] = await QuickMessage.findAll({ + order: [["shortcode", "ASC"]] + }); + return records; +}; + +export default FindAllService; diff --git a/backend/src/services/QuickMessageService/FindService.ts b/backend/src/services/QuickMessageService/FindService.ts new file mode 100644 index 0000000..67b5035 --- /dev/null +++ b/backend/src/services/QuickMessageService/FindService.ts @@ -0,0 +1,25 @@ +import { Op } from "sequelize"; +import QuickMessage from "../../models/QuickMessage"; +import Company from "../../models/Company"; + +type Params = { + companyId: string; + userId: string; +}; + +const FindService = async ({ companyId, userId }: Params): Promise => { + const notes: QuickMessage[] = await QuickMessage.findAll({ + where: { + [Op.or]: [ + { companyId, userId }, + { companyId, geral: true } + ] + }, + include: [{ model: Company, as: "company", attributes: ["id", "name"] }], + order: [["shortcode", "ASC"]] + }); + + return notes; +}; + +export default FindService; diff --git a/backend/src/services/QuickMessageService/ListService.ts b/backend/src/services/QuickMessageService/ListService.ts new file mode 100644 index 0000000..89fb973 --- /dev/null +++ b/backend/src/services/QuickMessageService/ListService.ts @@ -0,0 +1,67 @@ +import { Sequelize, Op, Filterable } from "sequelize"; +import QuickMessage from "../../models/QuickMessage"; + +interface Request { + searchParam?: string; + pageNumber?: string; + companyId: number | string; + userId?: number | string; +} + +interface Response { + records: QuickMessage[]; + count: number; + hasMore: boolean; +} + +const ListService = async ({ + searchParam = "", + pageNumber = "1", + companyId, + userId +}: Request): Promise => { + const sanitizedSearchParam = searchParam.toLocaleLowerCase().trim(); + + let whereCondition: Filterable["where"] = { + // [Op.or]: [ + // { + shortcode: Sequelize.where( + Sequelize.fn("LOWER", Sequelize.col("shortcode")), + "LIKE", + `%${sanitizedSearchParam}%` + ) + // }, + // { + // message: Sequelize.where( + // Sequelize.fn("LOWER", Sequelize.col("message")), + // "LIKE", + // `%${sanitizedSearchParam}%` + // ) + // } + // ] + }; + whereCondition = { + ...whereCondition, + companyId, + userId: userId + } + const limit = 20; + const offset = limit * (+pageNumber - 1); + + const { count, rows: records } = await QuickMessage.findAndCountAll({ + where: whereCondition, + limit, + offset, + order: [["shortcode", "ASC"]] + }); + + const hasMore = count > offset + records.length; + + return { + records, + count, + hasMore + }; +}; + +export default ListService; \ No newline at end of file diff --git a/backend/src/services/QuickMessageService/ShowService.ts b/backend/src/services/QuickMessageService/ShowService.ts new file mode 100644 index 0000000..a12282c --- /dev/null +++ b/backend/src/services/QuickMessageService/ShowService.ts @@ -0,0 +1,14 @@ +import QuickMessage from "../../models/QuickMessage"; +import AppError from "../../errors/AppError"; + +const ShowService = async (id: string | number): Promise => { + const record = await QuickMessage.findByPk(id); + + if (!record) { + throw new AppError("ERR_NO_TICKETNOTE_FOUND", 404); + } + + return record; +}; + +export default ShowService; diff --git a/backend/src/services/QuickMessageService/UpdateService.ts b/backend/src/services/QuickMessageService/UpdateService.ts new file mode 100644 index 0000000..47998f2 --- /dev/null +++ b/backend/src/services/QuickMessageService/UpdateService.ts @@ -0,0 +1,31 @@ +import AppError from "../../errors/AppError"; +import QuickMessage from "../../models/QuickMessage"; + +interface Data { + shortcode: string; + message: string; + userId: number | string; + id?: number | string; + geral?: boolean; +} + +const UpdateService = async (data: Data): Promise => { + const { id, shortcode, message, userId, geral } = data; + + const record = await QuickMessage.findByPk(id); + + if (!record) { + throw new AppError("ERR_NO_TICKETNOTE_FOUND", 404); + } + + await record.update({ + shortcode, + message, + userId, + geral + }); + + return record; +}; + +export default UpdateService; diff --git a/backend/src/services/ReportService/DashbardDataService.ts b/backend/src/services/ReportService/DashbardDataService.ts new file mode 100644 index 0000000..f4f6d2e --- /dev/null +++ b/backend/src/services/ReportService/DashbardDataService.ts @@ -0,0 +1,154 @@ +/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable camelcase */ +import { QueryTypes } from "sequelize"; +import * as _ from "lodash"; +import sequelize from "../../database"; + +export interface DashboardData { + counters: any; + attendants: []; +} + +export interface Params { + days?: number; + date_from?: string; + date_to?: string; +} + +export default async function DashboardDataService( + companyId: string | number, + params: Params +): Promise { + const query = ` + with + traking as ( + select + c.name "companyName", + u.name "userName", + u.online "userOnline", + w.name "whatsappName", + ct.name "contactName", + ct.number "contactNumber", + (tt."finishedAt" is not null) "finished", + (tt."userId" is null and tt."finishedAt" is null) "pending", + coalesce(( + (date_part('day', age(coalesce(tt."ratingAt", tt."finishedAt") , tt."startedAt")) * 24 * 60) + + (date_part('hour', age(coalesce(tt."ratingAt", tt."finishedAt"), tt."startedAt")) * 60) + + (date_part('minutes', age(coalesce(tt."ratingAt", tt."finishedAt"), tt."startedAt"))) + ), 0) "supportTime", + coalesce(( + (date_part('day', age(tt."startedAt", tt."queuedAt")) * 24 * 60) + + (date_part('hour', age(tt."startedAt", tt."queuedAt")) * 60) + + (date_part('minutes', age(tt."startedAt", tt."queuedAt"))) + ), 0) "waitTime", + t.status, + tt.*, + ct."id" "contactId" + from "TicketTraking" tt + left join "Companies" c on c.id = tt."companyId" + left join "Users" u on u.id = tt."userId" + left join "Whatsapps" w on w.id = tt."whatsappId" + left join "Tickets" t on t.id = tt."ticketId" + left join "Contacts" ct on ct.id = t."contactId" + -- filterPeriod + ), + counters as ( + select + (select avg("supportTime") from traking where "supportTime" > 0) "avgSupportTime", + (select avg("waitTime") from traking where "waitTime" > 0) "avgWaitTime", + ( + select count(distinct "id") + from "Tickets" + where status like 'open' and "companyId" = ? + ) "supportHappening", + ( + select count(distinct "id") + from "Tickets" + where status like 'pending' and "companyId" = ? + ) "supportPending", + (select count(id) from traking where finished) "supportFinished", + ( + select count(leads.id) from ( + select + ct1.id, + count(tt1.id) total + from traking tt1 + left join "Tickets" t1 on t1.id = tt1."ticketId" + left join "Contacts" ct1 on ct1.id = t1."contactId" + group by 1 + having count(tt1.id) = 1 + ) leads + ) "leads", + ( + select count(id) + from "Companies" + ) "totalCompanies", + ( + select count(id) + from "Whatsapps" + where session <> '' + ) "totalWhatsappSessions" + ), + attedants as ( + select + u.id, + u.name, + coalesce(att."avgSupportTime", 0) "avgSupportTime", + att.tickets, + att.rating, + att.online + from "Users" u + left join ( + select + u1.id, + u1."name", + u1."online", + avg(t."supportTime") "avgSupportTime", + count(t."id") tickets, + coalesce(avg(ur.rate), 0) rating + from "Users" u1 + left join traking t on t."userId" = u1.id + left join "UserRatings" ur on ur."userId" = t."userId" and ur."createdAt"::date = t."finishedAt"::date + group by 1, 2 + ) att on att.id = u.id + where u."companyId" = ? + order by att.name + ) + select + (select coalesce(jsonb_build_object('counters', c.*)->>'counters', '{}')::jsonb from counters c) counters, + (select coalesce(json_agg(a.*), '[]')::jsonb from attedants a) attendants; + `; + + let where = 'where tt."companyId" = ?'; + const replacements: any[] = [companyId]; + + if (_.has(params, "days")) { + where += ` and tt."queuedAt" >= (now() - '? days'::interval)`; + replacements.push(parseInt(`${params.days}`.replace(/\D/g, ""), 10)); + } + + if (_.has(params, "date_from")) { + where += ` and tt."queuedAt" >= ?`; + replacements.push(`${params.date_from} 00:00:00`); + } + + if (_.has(params, "date_to")) { + where += ` and tt."finishedAt" <= ?`; + replacements.push(`${params.date_to} 23:59:59`); + } + + replacements.push(companyId); + replacements.push(companyId); + replacements.push(companyId); + + const finalQuery = query.replace("-- filterPeriod", where); + + const responseData: DashboardData = await sequelize.query(finalQuery, { + replacements, + type: QueryTypes.SELECT, + plain: true + }); + + return responseData; +} + diff --git a/backend/src/services/ReportService/TicketsAttendance.ts b/backend/src/services/ReportService/TicketsAttendance.ts new file mode 100644 index 0000000..ecafcaa --- /dev/null +++ b/backend/src/services/ReportService/TicketsAttendance.ts @@ -0,0 +1,60 @@ +import sequelize from "../../database/index"; +import { QueryTypes } from "sequelize"; + +interface Return { + data: {}; +} + +interface Request { + initialDate: string; + finalDate: string; + companyId: number; +} + +interface DataReturn { + quantidade: number; + data?: number; + nome?: string; +} + +interface dataUser { + name: string; +} + +export const TicketsAttendance = async ({ initialDate, finalDate, companyId }: Request): Promise => { + + const sqlUsers = `select u.name from "Users" u where u."companyId" = ${companyId}` + + const users: dataUser[] = await sequelize.query(sqlUsers, { type: QueryTypes.SELECT }); + + const sql = ` + select + COUNT(*) AS quantidade, + u.name AS nome + from + "TicketTraking" tt + left join "Users" u on u.id = tt."userId" + where + tt."companyId" = ${companyId} + and "ticketId" is not null + and tt."userId" is not null + and tt."finishedAt" >= '${initialDate} 00:00:00' + and tt."finishedAt" <= '${finalDate} 23:59:59' + group by + nome + ORDER BY + nome asc` + + const data: DataReturn[] = await sequelize.query(sql, { type: QueryTypes.SELECT }); + + users.map(user => { + let indexCreated = data.findIndex((item) => item.nome === user.name); + + if (indexCreated === -1) { + data.push({ quantidade: 0, nome: user.name }) + } + + }) + + return { data }; +} diff --git a/backend/src/services/ReportService/TicketsDayService.ts b/backend/src/services/ReportService/TicketsDayService.ts new file mode 100644 index 0000000..d501e87 --- /dev/null +++ b/backend/src/services/ReportService/TicketsDayService.ts @@ -0,0 +1,70 @@ +import sequelize from "../../database/index"; +import { QueryTypes } from "sequelize"; + +interface Return { + data: {}; + count: number; +} + +interface Request { + initialDate: string; + finalDate: string; + companyId: number; +} + +interface DataReturn { + total: number; + data?: number; + horario?: string; +} + +export const TicketsDayService = async ({ initialDate, finalDate, companyId }: Request): Promise => { + + let sql = ''; + let count = 0; + + if (initialDate && initialDate.trim() === finalDate && finalDate.trim()) { + sql = ` + SELECT + COUNT(*) AS total, + extract(hour from tick."createdAt") AS horario + --to_char(DATE(tick."createdAt"), 'dd-mm-YYYY') as horario + FROM + "TicketTraking" tick + WHERE + tick."companyId" = ${companyId} + and DATE(tick."createdAt") >= '${initialDate} 00:00:00' + AND DATE(tick."createdAt") <= '${finalDate} 23:59:59' + GROUP BY + extract(hour from tick."createdAt") + --to_char(DATE(tick."createdAt"), 'dd-mm-YYYY') + ORDER BY + horario asc; + ` + } else { + sql = ` + SELECT + COUNT(*) AS total, + to_char(DATE(tick."createdAt"), 'dd/mm/YYYY') as data + FROM + "TicketTraking" tick + WHERE + tick."companyId" = ${companyId} + and DATE(tick."createdAt") >= '${initialDate}' + AND DATE(tick."createdAt") <= '${finalDate}' + GROUP BY + to_char(DATE(tick."createdAt"), 'dd/mm/YYYY') + ORDER BY + data asc; + ` + } + + const data: DataReturn[] = await sequelize.query(sql, { type: QueryTypes.SELECT }); + + data.forEach((register) => { + count += Number(register.total); + }) + + return { data, count }; + +} diff --git a/backend/src/services/ResetPasswordService/ResetPassword.ts b/backend/src/services/ResetPasswordService/ResetPassword.ts new file mode 100644 index 0000000..071db69 --- /dev/null +++ b/backend/src/services/ResetPasswordService/ResetPassword.ts @@ -0,0 +1,51 @@ +import sequelize from "sequelize"; +import database from "../../database"; +import { hash } from "bcryptjs"; +const ResetPassword = async ( + email: string, + token: string, + password: string +) => { + const { hasResult, data } = await filterUser(email, token); + if (!hasResult) { + return { status: 404, message: "Email não encontrado" }; + } + if (hasResult === true) { + try { + const convertPassword: string = await hash(password, 8); + const { hasResults, datas } = await insertHasPassword( + email, + token, + convertPassword + ); + if (datas.length === 0) { + return { status: 404, message: "Token não encontrado" }; + } + } catch (err) { + console.log(err); + } + } +}; +export default ResetPassword; +const filterUser = async (email: string, token: string) => { + const sql = `SELECT * FROM "Users" WHERE email = '${email}' AND "resetPassword" != ''`; + const result = await database.query(sql, { + type: sequelize.QueryTypes.SELECT + }); + return { hasResult: result.length > 0, data: result }; +}; +const insertHasPassword = async ( + email: string, + token: string, + convertPassword: string +) => { + const sqlValida = `SELECT * FROM "Users" WHERE email = '${email}' AND "resetPassword" = '${token}'`; + const resultado = await database.query(sqlValida, { + type: sequelize.QueryTypes.SELECT + }); + const sqls = `UPDATE "Users" SET "passwordHash"= '${convertPassword}' , "resetPassword" = '' WHERE email= '${email}' AND "resetPassword" = '${token}'`; + const results = await database.query(sqls, { + type: sequelize.QueryTypes.UPDATE + }); + return { hasResults: results.length > 0, datas: resultado }; +}; diff --git a/backend/src/services/ResetPasswordService/ResetPassword.ts.bak b/backend/src/services/ResetPasswordService/ResetPassword.ts.bak new file mode 100644 index 0000000..411f45e --- /dev/null +++ b/backend/src/services/ResetPasswordService/ResetPassword.ts.bak @@ -0,0 +1,48 @@ +import sequelize from "sequelize"; +import database from "../../database"; +import { hash } from "bcryptjs"; + +const ResetPassword = async (email: string ,token: string, password: string) => { + + const {hasResult , data} = await filterUser(email, token); + + if (!hasResult) { + return { status: 404, message: "Email não encontrado" }; + } + + if(hasResult === true){ + try{ + const convertPassword: string= await hash(password,8) + + const {hasResults , datas} = await insertHasPassword(email, token ,convertPassword); + + if (datas.length === 0){ + return { status: 404, message: "Token não encontrado" }; + } + + }catch(err){ + console.log(err) + } + } + +} +export default ResetPassword; + +const filterUser = async (email : string , token: string)=>{ + const sql = `SELECT * FROM "Users" WHERE email = '${email}' AND "resetPassword" != ''`; + const result = await database.query(sql, { type: sequelize.QueryTypes.SELECT }); + return { hasResult: result.length > 0, data: result }; +} +const insertHasPassword = async (email : string , token: string, convertPassword: string)=>{ + + + const sqlValida = `SELECT * FROM "Users" WHERE email = '${email}' AND "resetPassword" = '${token}'`; + const resultado = await database.query(sqlValida, { type: sequelize.QueryTypes.SELECT }); + + + const sqls = `UPDATE "Users" SET "passwordHash"= '${convertPassword}' , "resetPassword" = '' WHERE email= '${email}' AND "resetPassword" = '${token}'`; + const results = await database.query(sqls, { type: sequelize.QueryTypes.UPDATE }); + + + return { hasResults: results.length > 0, datas: resultado}; +} \ No newline at end of file diff --git a/backend/src/services/ScheduleServices/CreateService.ts b/backend/src/services/ScheduleServices/CreateService.ts new file mode 100644 index 0000000..0454976 --- /dev/null +++ b/backend/src/services/ScheduleServices/CreateService.ts @@ -0,0 +1,48 @@ +import * as Yup from "yup"; + +import AppError from "../../errors/AppError"; +import Schedule from "../../models/Schedule"; + +interface Request { + body: string; + sendAt: string; + contactId: number | string; + companyId: number | string; + userId?: number | string; +} + +const CreateService = async ({ + body, + sendAt, + contactId, + companyId, + userId +}: Request): Promise => { + const schema = Yup.object().shape({ + body: Yup.string().required().min(5), + sendAt: Yup.string().required() + }); + + try { + await schema.validate({ body, sendAt }); + } catch (err: any) { + throw new AppError(err.message); + } + + const schedule = await Schedule.create( + { + body, + sendAt, + contactId, + companyId, + userId, + status: 'PENDENTE' + } + ); + + await schedule.reload(); + + return schedule; +}; + +export default CreateService; diff --git a/backend/src/services/ScheduleServices/DeleteService.ts b/backend/src/services/ScheduleServices/DeleteService.ts new file mode 100644 index 0000000..bdda0c2 --- /dev/null +++ b/backend/src/services/ScheduleServices/DeleteService.ts @@ -0,0 +1,16 @@ +import Schedule from "../../models/Schedule"; +import AppError from "../../errors/AppError"; + +const DeleteService = async (id: string | number, companyId: number): Promise => { + const schedule = await Schedule.findOne({ + where: { id, companyId } + }); + + if (!schedule) { + throw new AppError("ERR_NO_SCHEDULE_FOUND", 404); + } + + await schedule.destroy(); +}; + +export default DeleteService; diff --git a/backend/src/services/ScheduleServices/ListService.ts b/backend/src/services/ScheduleServices/ListService.ts new file mode 100644 index 0000000..14b193b --- /dev/null +++ b/backend/src/services/ScheduleServices/ListService.ts @@ -0,0 +1,93 @@ +import { Op, Sequelize } from "sequelize"; +import Contact from "../../models/Contact"; +import Schedule from "../../models/Schedule"; +import User from "../../models/User"; + +interface Request { + searchParam?: string; + contactId?: number | string; + userId?: number | string; + companyId?: number; + pageNumber?: string | number; +} + +interface Response { + schedules: Schedule[]; + count: number; + hasMore: boolean; +} + +const ListService = async ({ + searchParam, + contactId = "", + userId = "", + pageNumber = "1", + companyId +}: Request): Promise => { + let whereCondition = {}; + const limit = 20; + const offset = limit * (+pageNumber - 1); + + if (searchParam) { + whereCondition = { + [Op.or]: [ + { + "$Schedule.body$": Sequelize.where( + Sequelize.fn("LOWER", Sequelize.col("Schedule.body")), + "LIKE", + `%${searchParam.toLowerCase()}%` + ) + }, + { + "$Contact.name$": Sequelize.where( + Sequelize.fn("LOWER", Sequelize.col("contact.name")), + "LIKE", + `%${searchParam.toLowerCase()}%` + ) + }, + ], + } + } + + if (contactId !== "") { + whereCondition = { + ...whereCondition, + contactId + } + } + + if (userId !== "") { + whereCondition = { + ...whereCondition, + userId + } + } + + whereCondition = { + ...whereCondition, + companyId: { + [Op.eq]: companyId + } + } + + const { count, rows: schedules } = await Schedule.findAndCountAll({ + where: whereCondition, + limit, + offset, + order: [["createdAt", "DESC"]], + include: [ + { model: Contact, as: "contact", attributes: ["id", "name"] }, + { model: User, as: "user", attributes: ["id", "name"] }, + ] + }); + + const hasMore = count > offset + schedules.length; + + return { + schedules, + count, + hasMore + }; +}; + +export default ListService; diff --git a/backend/src/services/ScheduleServices/ShowService.ts b/backend/src/services/ScheduleServices/ShowService.ts new file mode 100644 index 0000000..6237703 --- /dev/null +++ b/backend/src/services/ScheduleServices/ShowService.ts @@ -0,0 +1,25 @@ +import Schedule from "../../models/Schedule"; +import AppError from "../../errors/AppError"; +import Contact from "../../models/Contact"; +import User from "../../models/User"; + +const ScheduleService = async (id: string | number, companyId: number): Promise => { + const schedule = await Schedule.findByPk(id, { + include: [ + { model: Contact, as: "contact", attributes: ["id", "name"] }, + { model: User, as: "user", attributes: ["id", "name"] }, + ] + }); + + if (schedule?.companyId !== companyId) { + throw new AppError("Não é possível excluir registro de outra empresa"); + } + + if (!schedule) { + throw new AppError("ERR_NO_SCHEDULE_FOUND", 404); + } + + return schedule; +}; + +export default ScheduleService; diff --git a/backend/src/services/ScheduleServices/UpdateService.ts b/backend/src/services/ScheduleServices/UpdateService.ts new file mode 100644 index 0000000..649ca5c --- /dev/null +++ b/backend/src/services/ScheduleServices/UpdateService.ts @@ -0,0 +1,67 @@ +import * as Yup from "yup"; + +import AppError from "../../errors/AppError"; +import Schedule from "../../models/Schedule"; +import ShowService from "./ShowService"; + +interface ScheduleData { + id?: number; + body?: string; + sendAt?: string; + sentAt?: string; + contactId?: number; + companyId?: number; + ticketId?: number; + userId?: number; +} + +interface Request { + scheduleData: ScheduleData; + id: string | number; + companyId: number; +} + +const UpdateUserService = async ({ + scheduleData, + id, + companyId +}: Request): Promise => { + const schedule = await ShowService(id, companyId); + + if (schedule?.companyId !== companyId) { + throw new AppError("Não é possível alterar registros de outra empresa"); + } + + const schema = Yup.object().shape({ + body: Yup.string().min(5) + }); + + const { + body, + sendAt, + sentAt, + contactId, + ticketId, + userId, + } = scheduleData; + + try { + await schema.validate({ body }); + } catch (err: any) { + throw new AppError(err.message); + } + + await schedule.update({ + body, + sendAt, + sentAt, + contactId, + ticketId, + userId, + }); + + await schedule.reload(); + return schedule; +}; + +export default UpdateUserService; diff --git a/backend/src/services/SettingServices/ListSettingsService.ts b/backend/src/services/SettingServices/ListSettingsService.ts new file mode 100644 index 0000000..19853e3 --- /dev/null +++ b/backend/src/services/SettingServices/ListSettingsService.ts @@ -0,0 +1,19 @@ +import Setting from "../../models/Setting"; + +interface Request { + companyId: number; +} + +const ListSettingsService = async ({ + companyId +}: Request): Promise => { + const settings = await Setting.findAll({ + where: { + companyId + } + }); + + return settings; +}; + +export default ListSettingsService; diff --git a/backend/src/services/SettingServices/ListSettingsServiceOne.ts b/backend/src/services/SettingServices/ListSettingsServiceOne.ts new file mode 100644 index 0000000..4d64221 --- /dev/null +++ b/backend/src/services/SettingServices/ListSettingsServiceOne.ts @@ -0,0 +1,22 @@ +import Setting from "../../models/Setting"; + +interface Request { + companyId: number; + key?: string; +} + +const ListSettingsServiceOne = async ({ + companyId, + key +}: Request): Promise => { + const setting = await Setting.findOne({ + where: { + companyId, + ...(key && { key }) + } + }); + + return setting; +}; + +export default ListSettingsServiceOne; \ No newline at end of file diff --git a/backend/src/services/SettingServices/ShowSettingsService.ts b/backend/src/services/SettingServices/ShowSettingsService.ts new file mode 100644 index 0000000..c3e791d --- /dev/null +++ b/backend/src/services/SettingServices/ShowSettingsService.ts @@ -0,0 +1,24 @@ +import AppError from "../../errors/AppError"; +import Setting from "../../models/Setting"; + +interface Request { + settingKey: string; // Add settingKey property + companyId: number; +} + +const ShowSettingsService = async ({ + settingKey, // Update parameter name to settingKey + companyId +}: Request): Promise => { + const setting = await Setting.findOne({ + where: { key: settingKey, companyId } // Update key to settingKey + }); + + if (!setting) { + throw new AppError("ERR_NO_SETTING_FOUND", 404); + } + + return setting; +}; + +export default ShowSettingsService; \ No newline at end of file diff --git a/backend/src/services/SettingServices/UpdateSettingService.ts b/backend/src/services/SettingServices/UpdateSettingService.ts new file mode 100644 index 0000000..af05567 --- /dev/null +++ b/backend/src/services/SettingServices/UpdateSettingService.ts @@ -0,0 +1,40 @@ +import AppError from "../../errors/AppError"; +import Setting from "../../models/Setting"; + +interface Request { + key: string; + value: string; + companyId: number; +} + +const UpdateSettingService = async ({ + key, + value, + companyId +}: Request): Promise => { + const [setting] = await Setting.findOrCreate({ + where: { + key, + companyId + }, + defaults: { + key, + value, + companyId + } + }); + + if (setting != null && setting?.companyId !== companyId) { + throw new AppError("Não é possível consultar registros de outra empresa"); + } + + if (!setting) { + throw new AppError("ERR_NO_SETTING_FOUND", 404); + } + + await setting.update({ value }); + + return setting; +}; + +export default UpdateSettingService; diff --git a/backend/src/services/TagServices/CreateService.ts b/backend/src/services/TagServices/CreateService.ts new file mode 100644 index 0000000..45527a4 --- /dev/null +++ b/backend/src/services/TagServices/CreateService.ts @@ -0,0 +1,39 @@ +import * as Yup from "yup"; + +import AppError from "../../errors/AppError"; +import Tag from "../../models/Tag"; + +interface Request { + name: string; + color: string; + kanban: number; + companyId: number; +} + +const CreateService = async ({ + name, + color = "#A4CCCC", + kanban = 0, + companyId +}: Request): Promise => { + const schema = Yup.object().shape({ + name: Yup.string().required().min(3) + }); + + try { + await schema.validate({ name }); + } catch (err: any) { + throw new AppError(err.message); + } + + const [tag] = await Tag.findOrCreate({ + where: { name, color, companyId, kanban }, + defaults: { name, color, companyId, kanban } + }); + + await tag.reload(); + + return tag; +}; + +export default CreateService; diff --git a/backend/src/services/TagServices/DeleteService.ts b/backend/src/services/TagServices/DeleteService.ts new file mode 100644 index 0000000..9d81b7b --- /dev/null +++ b/backend/src/services/TagServices/DeleteService.ts @@ -0,0 +1,16 @@ +import Tag from "../../models/Tag"; +import AppError from "../../errors/AppError"; + +const DeleteService = async (id: string | number): Promise => { + const tag = await Tag.findOne({ + where: { id } + }); + + if (!tag) { + throw new AppError("ERR_NO_TAG_FOUND", 404); + } + + await tag.destroy(); +}; + +export default DeleteService; diff --git a/backend/src/services/TagServices/KanbanListService.ts b/backend/src/services/TagServices/KanbanListService.ts new file mode 100644 index 0000000..f999a41 --- /dev/null +++ b/backend/src/services/TagServices/KanbanListService.ts @@ -0,0 +1,24 @@ +import { Op } from "sequelize"; +import Tag from "../../models/Tag"; +import Ticket from "../../models/Ticket"; +import TicketTag from "../../models/TicketTag"; + +interface Request { + companyId: number; +} + +const KanbanListService = async ({ + companyId +}: Request): Promise => { + const tags = await Tag.findAll({ + where: { + kanban: 1, + companyId: companyId, + }, + order: [["id", "ASC"]], + raw: true, + }); + return tags; +}; + +export default KanbanListService; diff --git a/backend/src/services/TagServices/ListService.ts b/backend/src/services/TagServices/ListService.ts new file mode 100644 index 0000000..b07787d --- /dev/null +++ b/backend/src/services/TagServices/ListService.ts @@ -0,0 +1,66 @@ +import { Op, literal, fn, col } from "sequelize"; +import Tag from "../../models/Tag"; +import Ticket from "../../models/Ticket"; +import TicketTag from "../../models/TicketTag"; + +interface Request { + companyId: number; + searchParam?: string; + pageNumber?: string | number; +} + +interface Response { + tags: Tag[]; + count: number; + hasMore: boolean; +} + +const ListService = async ({ + companyId, + searchParam, + pageNumber = "1" +}: Request): Promise => { + let whereCondition = {}; + const limit = 5000; + const offset = limit * (+pageNumber - 1); + + if (searchParam) { + whereCondition = { + [Op.or]: [ + { name: { [Op.like]: `%${searchParam}%` } }, + { color: { [Op.like]: `%${searchParam}%` } } + ] + }; + } + + const { count, rows: tags } = await Tag.findAndCountAll({ + where: { ...whereCondition, companyId }, + limit, + offset, + order: [["name", "ASC"]], + subQuery: false, + include: [{ + model: TicketTag, + as: 'ticketTags', + attributes: [], + required: false + }], + attributes: [ + 'id', + 'name', + 'color', + [fn('count', col('ticketTags.tagId')), 'ticketsCount'] + ], + group: ['Tag.id'] + }); + + const hasMore = count > offset + tags.length; + + return { + tags, + count, + hasMore + }; +}; + +export default ListService; diff --git a/backend/src/services/TagServices/ShowService.ts b/backend/src/services/TagServices/ShowService.ts new file mode 100644 index 0000000..fec4ade --- /dev/null +++ b/backend/src/services/TagServices/ShowService.ts @@ -0,0 +1,14 @@ +import Tag from "../../models/Tag"; +import AppError from "../../errors/AppError"; + +const TagService = async (id: string | number): Promise => { + const tag = await Tag.findByPk(id); + + if (!tag) { + throw new AppError("ERR_NO_TAG_FOUND", 404); + } + + return tag; +}; + +export default TagService; diff --git a/backend/src/services/TagServices/SimpleListService.ts b/backend/src/services/TagServices/SimpleListService.ts new file mode 100644 index 0000000..451cb93 --- /dev/null +++ b/backend/src/services/TagServices/SimpleListService.ts @@ -0,0 +1,34 @@ +import { Op, Sequelize } from "sequelize"; +import Tag from "../../models/Tag"; +import Ticket from "../../models/Ticket"; +import TicketTag from "../../models/TicketTag"; + +interface Request { + companyId: number; + searchParam?: string; +} + +const ListService = async ({ + companyId, + searchParam +}: Request): Promise => { + let whereCondition = {}; + + if (searchParam) { + whereCondition = { + [Op.or]: [ + { name: { [Op.like]: `%${searchParam}%` } }, + { color: { [Op.like]: `%${searchParam}%` } } + ] + }; + } + + const tags = await Tag.findAll({ + where: { ...whereCondition, companyId }, + order: [["name", "ASC"]] + }); + + return tags; +}; + +export default ListService; diff --git a/backend/src/services/TagServices/SyncTagsService.ts b/backend/src/services/TagServices/SyncTagsService.ts new file mode 100644 index 0000000..18ef7c0 --- /dev/null +++ b/backend/src/services/TagServices/SyncTagsService.ts @@ -0,0 +1,26 @@ +import Tag from "../../models/Tag"; +import Ticket from "../../models/Ticket"; +import TicketTag from "../../models/TicketTag"; + +interface Request { + tags: Tag[]; + ticketId: number; +} + +const SyncTags = async ({ + tags, + ticketId +}: Request): Promise => { + const ticket = await Ticket.findByPk(ticketId, { include: [Tag] }); + + const tagList = tags.map(t => ({ tagId: t.id, ticketId })); + + await TicketTag.destroy({ where: { ticketId } }); + await TicketTag.bulkCreate(tagList); + + ticket?.reload(); + + return ticket; +}; + +export default SyncTags; diff --git a/backend/src/services/TagServices/UpdateService.ts b/backend/src/services/TagServices/UpdateService.ts new file mode 100644 index 0000000..06889ad --- /dev/null +++ b/backend/src/services/TagServices/UpdateService.ts @@ -0,0 +1,47 @@ +import * as Yup from "yup"; + +import AppError from "../../errors/AppError"; +import Tag from "../../models/Tag"; +import ShowService from "./ShowService"; + +interface TagData { + id?: number; + name?: string; + color?: string; + kanban?: number; +} + +interface Request { + tagData: TagData; + id: string | number; +} + +const UpdateUserService = async ({ + tagData, + id +}: Request): Promise => { + const tag = await ShowService(id); + + const schema = Yup.object().shape({ + name: Yup.string().min(3) + }); + + const { name, color, kanban } = tagData; + + try { + await schema.validate({ name }); + } catch (err: any) { + throw new AppError(err.message); + } + + await tag.update({ + name, + color, + kanban + }); + + await tag.reload(); + return tag; +}; + +export default UpdateUserService; diff --git a/backend/src/services/TicketNoteService/CreateTicketNoteService.ts b/backend/src/services/TicketNoteService/CreateTicketNoteService.ts new file mode 100644 index 0000000..08b6518 --- /dev/null +++ b/backend/src/services/TicketNoteService/CreateTicketNoteService.ts @@ -0,0 +1,34 @@ +import * as Yup from "yup"; +import AppError from "../../errors/AppError"; +import TicketNote from "../../models/TicketNote"; + +interface TicketNoteData { + note: string; + userId: number | string; + contactId: number | string; + ticketId: number | string; +} + +const CreateTicketNoteService = async ( + ticketNoteData: TicketNoteData +): Promise => { + const { note } = ticketNoteData; + + const ticketnoteSchema = Yup.object().shape({ + note: Yup.string() + .min(3, "ERR_TICKETNOTE_INVALID_NAME") + .required("ERR_TICKETNOTE_INVALID_NAME") + }); + + try { + await ticketnoteSchema.validate({ note }); + } catch (err) { + throw new AppError(err.message); + } + + const ticketNote = await TicketNote.create(ticketNoteData); + + return ticketNote; +}; + +export default CreateTicketNoteService; diff --git a/backend/src/services/TicketNoteService/DeleteTicketNoteService.ts b/backend/src/services/TicketNoteService/DeleteTicketNoteService.ts new file mode 100644 index 0000000..5d8f9fe --- /dev/null +++ b/backend/src/services/TicketNoteService/DeleteTicketNoteService.ts @@ -0,0 +1,16 @@ +import TicketNote from "../../models/TicketNote"; +import AppError from "../../errors/AppError"; + +const DeleteTicketNoteService = async (id: string): Promise => { + const ticketnote = await TicketNote.findOne({ + where: { id } + }); + + if (!ticketnote) { + throw new AppError("ERR_NO_TICKETNOTE_FOUND", 404); + } + + await ticketnote.destroy(); +}; + +export default DeleteTicketNoteService; diff --git a/backend/src/services/TicketNoteService/FindAllTicketNotesService.ts b/backend/src/services/TicketNoteService/FindAllTicketNotesService.ts new file mode 100644 index 0000000..57fc19e --- /dev/null +++ b/backend/src/services/TicketNoteService/FindAllTicketNotesService.ts @@ -0,0 +1,8 @@ +import TicketNote from "../../models/TicketNote"; + +const FindAllTicketNotesService = async (): Promise => { + const ticketNote = await TicketNote.findAll(); + return ticketNote; +}; + +export default FindAllTicketNotesService; diff --git a/backend/src/services/TicketNoteService/FindNotesByContactIdAndTicketId.ts b/backend/src/services/TicketNoteService/FindNotesByContactIdAndTicketId.ts new file mode 100644 index 0000000..bd01d0e --- /dev/null +++ b/backend/src/services/TicketNoteService/FindNotesByContactIdAndTicketId.ts @@ -0,0 +1,31 @@ +import TicketNote from "../../models/TicketNote"; +import User from "../../models/User"; +import Contact from "../../models/Contact"; +import Ticket from "../../models/Ticket"; + +interface Params { + contactId: number | string; + ticketId: number | string; +} + +const FindNotesByContactIdAndTicketId = async ({ + contactId, + ticketId +}: Params): Promise => { + const notes: TicketNote[] = await TicketNote.findAll({ + where: { + contactId, + ticketId + }, + include: [ + { model: User, as: "user", attributes: ["id", "name", "email"] }, + { model: Contact, as: "contact", attributes: ["id", "name"] }, + { model: Ticket, as: "ticket", attributes: ["id", "status", "createdAt"] } + ], + order: [["createdAt", "DESC"]] + }); + + return notes; +}; + +export default FindNotesByContactIdAndTicketId; diff --git a/backend/src/services/TicketNoteService/ListTicketNotesService.ts b/backend/src/services/TicketNoteService/ListTicketNotesService.ts new file mode 100644 index 0000000..900061e --- /dev/null +++ b/backend/src/services/TicketNoteService/ListTicketNotesService.ts @@ -0,0 +1,49 @@ +import { Sequelize, Op } from "sequelize"; +import TicketNote from "../../models/TicketNote"; + +interface Request { + searchParam?: string; + pageNumber?: string; +} + +interface Response { + ticketNotes: TicketNote[]; + count: number; + hasMore: boolean; +} + +const ListTicketNotesService = async ({ + searchParam = "", + pageNumber = "1" +}: Request): Promise => { + const whereCondition = { + [Op.or]: [ + { + note: Sequelize.where( + Sequelize.fn("LOWER", Sequelize.col("note")), + "LIKE", + `%${searchParam.toLowerCase().trim()}%` + ) + } + ] + }; + const limit = 20; + const offset = limit * (+pageNumber - 1); + + const { count, rows: ticketNotes } = await TicketNote.findAndCountAll({ + where: whereCondition, + limit, + offset, + order: [["createdAt", "DESC"]] + }); + + const hasMore = count > offset + ticketNotes.length; + + return { + ticketNotes, + count, + hasMore + }; +}; + +export default ListTicketNotesService; diff --git a/backend/src/services/TicketNoteService/ShowTicketNoteService.ts b/backend/src/services/TicketNoteService/ShowTicketNoteService.ts new file mode 100644 index 0000000..ead2ae6 --- /dev/null +++ b/backend/src/services/TicketNoteService/ShowTicketNoteService.ts @@ -0,0 +1,16 @@ +import TicketNote from "../../models/TicketNote"; +import AppError from "../../errors/AppError"; + +const ShowTicketNoteService = async ( + id: string | number +): Promise => { + const ticketNote = await TicketNote.findByPk(id); + + if (!ticketNote) { + throw new AppError("ERR_NO_TICKETNOTE_FOUND", 404); + } + + return ticketNote; +}; + +export default ShowTicketNoteService; diff --git a/backend/src/services/TicketNoteService/UpdateTicketNoteService.ts b/backend/src/services/TicketNoteService/UpdateTicketNoteService.ts new file mode 100644 index 0000000..a656260 --- /dev/null +++ b/backend/src/services/TicketNoteService/UpdateTicketNoteService.ts @@ -0,0 +1,27 @@ +import AppError from "../../errors/AppError"; +import TicketNote from "../../models/TicketNote"; + +interface TicketNoteData { + note: string; + id?: number | string; +} + +const UpdateTicketNoteService = async ( + ticketNoteData: TicketNoteData +): Promise => { + const { id, note } = ticketNoteData; + + const ticketNote = await TicketNote.findByPk(id); + + if (!ticketNote) { + throw new AppError("ERR_NO_TICKETNOTE_FOUND", 404); + } + + await ticketNote.update({ + note + }); + + return ticketNote; +}; + +export default UpdateTicketNoteService; diff --git a/backend/src/services/TicketServices/CreateTicketService.ts b/backend/src/services/TicketServices/CreateTicketService.ts new file mode 100644 index 0000000..528e912 --- /dev/null +++ b/backend/src/services/TicketServices/CreateTicketService.ts @@ -0,0 +1,82 @@ +import AppError from "../../errors/AppError"; +import CheckContactOpenTickets from "../../helpers/CheckContactOpenTickets"; +import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp"; +import Ticket from "../../models/Ticket"; +import ShowContactService from "../ContactServices/ShowContactService"; +import { getIO } from "../../libs/socket"; +import GetDefaultWhatsAppByUser from "../../helpers/GetDefaultWhatsAppByUser"; +import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService"; + +interface Request { + contactId: number; + status: string; + userId: number; + companyId: number; + queueId?: number; + whatsappId?: string; +} + +const CreateTicketService = async ({ + contactId, + status, + userId, + queueId, + companyId, + whatsappId +}: Request): Promise => { + let whatsapp; + + if (whatsappId !== undefined && whatsappId !== null && whatsappId !== "") { + whatsapp = await ShowWhatsAppService(whatsappId, companyId) + } + + let defaultWhatsapp = await GetDefaultWhatsAppByUser(userId); + + if (whatsapp) { + defaultWhatsapp = whatsapp; + } + if (!defaultWhatsapp) + defaultWhatsapp = await GetDefaultWhatsApp(companyId); + + await CheckContactOpenTickets(contactId, whatsappId); + + const { isGroup } = await ShowContactService(contactId, companyId); + + const [{ id }] = await Ticket.findOrCreate({ + where: { + contactId, + companyId, + whatsappId + }, + defaults: { + contactId, + companyId, + whatsappId: defaultWhatsapp.id, + status, + isGroup, + userId + } + }); + + await Ticket.update( + { companyId, queueId, userId, whatsappId: defaultWhatsapp.id, status: "open" }, + { where: { id } } + ); + + const ticket = await Ticket.findByPk(id, { include: ["contact", "queue"] }); + + if (!ticket) { + throw new AppError("ERR_CREATING_TICKET"); + } + + const io = getIO(); + + io.to(ticket.id.toString()).emit("ticket", { + action: "update", + ticket + }); + + return ticket; +}; + +export default CreateTicketService; diff --git a/backend/src/services/TicketServices/DeleteTicketService.ts b/backend/src/services/TicketServices/DeleteTicketService.ts new file mode 100644 index 0000000..b8c44d4 --- /dev/null +++ b/backend/src/services/TicketServices/DeleteTicketService.ts @@ -0,0 +1,28 @@ +import Ticket from "../../models/Ticket"; +import AppError from "../../errors/AppError"; +import TicketTraking from "../../models/TicketTraking"; + +const DeleteTicketService = async (id: string): Promise => { + const ticket = await Ticket.findOne({ + where: { id } + }); + + if (!ticket) { + throw new AppError("ERR_NO_TICKET_FOUND", 404); + } + + const tracking = await TicketTraking.findOne({ + where: { ticketId: ticket.id } + }); + if (tracking) { + tracking.finishedAt = new Date(); + tracking.save(); + } + await tracking.save(); + + await ticket.destroy(); + + return ticket; +}; + +export default DeleteTicketService; diff --git a/backend/src/services/TicketServices/FindOrCreateATicketTrakingService.ts b/backend/src/services/TicketServices/FindOrCreateATicketTrakingService.ts new file mode 100644 index 0000000..80d0df3 --- /dev/null +++ b/backend/src/services/TicketServices/FindOrCreateATicketTrakingService.ts @@ -0,0 +1,40 @@ +import { Op } from "sequelize"; +import TicketTraking from "../../models/TicketTraking"; + +interface Params { + ticketId: string | number; + companyId: string | number; + whatsappId?: string | number; + userId?: string | number; +} + +const FindOrCreateATicketTrakingService = async ({ + ticketId, + companyId, + whatsappId, + userId +}: Params): Promise => { + const ticketTraking = await TicketTraking.findOne({ + where: { + ticketId, + finishedAt: { + [Op.is]: null + } + } + }); + + if (ticketTraking) { + return ticketTraking; + } + + const newRecord = await TicketTraking.create({ + ticketId, + companyId, + whatsappId, + userId + }); + + return newRecord; +}; + +export default FindOrCreateATicketTrakingService; diff --git a/backend/src/services/TicketServices/FindOrCreateTicketService.ts b/backend/src/services/TicketServices/FindOrCreateTicketService.ts new file mode 100644 index 0000000..ca1cf9b --- /dev/null +++ b/backend/src/services/TicketServices/FindOrCreateTicketService.ts @@ -0,0 +1,128 @@ +import { subHours } from "date-fns"; +import { Op } from "sequelize"; +import Contact from "../../models/Contact"; +import Ticket from "../../models/Ticket"; +import ShowTicketService from "./ShowTicketService"; +import FindOrCreateATicketTrakingService from "./FindOrCreateATicketTrakingService"; +import Setting from "../../models/Setting"; +import Whatsapp from "../../models/Whatsapp"; + +interface TicketData { + status?: string; + companyId?: number; + unreadMessages?: number; +} + +const FindOrCreateTicketService = async ( + contact: Contact, + whatsappId: number, + unreadMessages: number, + companyId: number, + groupContact?: Contact +): Promise => { + let ticket = await Ticket.findOne({ + where: { + status: { + [Op.or]: ["open", "pending", "closed"] + }, + contactId: groupContact ? groupContact.id : contact.id, + companyId, + whatsappId + }, + order: [["id", "DESC"]] + }); + + if (ticket) { + await ticket.update({ unreadMessages, whatsappId }); + } + + if (ticket?.status === "closed") { + await ticket.update({ queueId: null, userId: null }); + } + + if (!ticket && groupContact) { + ticket = await Ticket.findOne({ + where: { + contactId: groupContact.id + }, + order: [["updatedAt", "DESC"]] + }); + + if (ticket) { + await ticket.update({ + status: "pending", + userId: null, + unreadMessages, + queueId: null, + companyId + }); + await FindOrCreateATicketTrakingService({ + ticketId: ticket.id, + companyId, + whatsappId: ticket.whatsappId, + userId: ticket.userId + }); + } + const msgIsGroupBlock = await Setting.findOne({ + where: { key: "timeCreateNewTicket" } + }); + + const value = msgIsGroupBlock ? parseInt(msgIsGroupBlock.value, 10) : 7200; + } + + if (!ticket && !groupContact) { + ticket = await Ticket.findOne({ + where: { + updatedAt: { + [Op.between]: [+subHours(new Date(), 2), +new Date()] + }, + contactId: contact.id + }, + order: [["updatedAt", "DESC"]] + }); + + if (ticket) { + await ticket.update({ + status: "pending", + userId: null, + unreadMessages, + queueId: null, + companyId + }); + await FindOrCreateATicketTrakingService({ + ticketId: ticket.id, + companyId, + whatsappId: ticket.whatsappId, + userId: ticket.userId + }); + } + } + + const whatsapp = await Whatsapp.findOne({ + where: { id: whatsappId } + }); + + if (!ticket) { + ticket = await Ticket.create({ + contactId: groupContact ? groupContact.id : contact.id, + status: "pending", + isGroup: !!groupContact, + unreadMessages, + whatsappId, + whatsapp, + companyId + }); + await FindOrCreateATicketTrakingService({ + ticketId: ticket.id, + companyId, + whatsappId, + userId: ticket.userId + }); + } + + ticket = await ShowTicketService(ticket.id, companyId); + + return ticket; +}; + +export default FindOrCreateTicketService; diff --git a/backend/src/services/TicketServices/ListTicketsService.ts b/backend/src/services/TicketServices/ListTicketsService.ts new file mode 100644 index 0000000..5223b89 --- /dev/null +++ b/backend/src/services/TicketServices/ListTicketsService.ts @@ -0,0 +1,237 @@ +import { Op, fn, where, col, Filterable, Includeable } from "sequelize"; +import { startOfDay, endOfDay, parseISO } from "date-fns"; + +import Ticket from "../../models/Ticket"; +import Contact from "../../models/Contact"; +import Message from "../../models/Message"; +import Queue from "../../models/Queue"; +import User from "../../models/User"; +import ShowUserService from "../UserServices/ShowUserService"; +import Tag from "../../models/Tag"; +import TicketTag from "../../models/TicketTag"; +import { intersection } from "lodash"; +import Whatsapp from "../../models/Whatsapp"; + +interface Request { + searchParam?: string; + pageNumber?: string; + status?: string; + date?: string; + updatedAt?: string; + showAll?: string; + userId: string; + withUnreadMessages?: string; + queueIds: number[]; + tags: number[]; + users: number[]; + companyId: number; +} + +interface Response { + tickets: Ticket[]; + count: number; + hasMore: boolean; +} + +const ListTicketsService = async ({ + searchParam = "", + pageNumber = "1", + queueIds, + tags, + users, + status, + date, + updatedAt, + showAll, + userId, + withUnreadMessages, + companyId +}: Request): Promise => { + let whereCondition: Filterable["where"] = { + [Op.or]: [{ userId }, { status: "pending" }], + queueId: { [Op.or]: [queueIds, null] } + }; + let includeCondition: Includeable[]; + + includeCondition = [ + { + model: Contact, + as: "contact", + attributes: ["id", "name", "number", "email", "profilePicUrl", "messengerId", "instagramId"] + }, + { + model: Queue, + as: "queue", + attributes: ["id", "name", "color"] + }, + { + model: User, + as: "user", + attributes: ["id", "name"] + }, + { + model: Tag, + as: "tags", + attributes: ["id", "name", "color"] + }, + { + model: Whatsapp, + as: "whatsapp", + attributes: ["name","type"] + }, + ]; + + if (showAll === "true") { + whereCondition = { queueId: { [Op.or]: [queueIds, null] } }; + } + + if (status) { + whereCondition = { + ...whereCondition, + status + }; + } + + if (searchParam) { + const sanitizedSearchParam = searchParam.toLocaleLowerCase().trim(); + + includeCondition = [ + ...includeCondition, + { + model: Message, + as: "messages", + attributes: ["id", "body"], + where: { + body: where( + fn("LOWER", col("body")), + "LIKE", + `%${sanitizedSearchParam}%` + ) + }, + required: false, + duplicating: false + } + ]; + + whereCondition = { + ...whereCondition, + [Op.or]: [ + { + "$contact.name$": where( + fn("LOWER", col("contact.name")), + "LIKE", + `%${sanitizedSearchParam}%` + ) + }, + { "$contact.number$": { [Op.like]: `%${sanitizedSearchParam}%` } }, + { + "$message.body$": where( + fn("LOWER", col("body")), + "LIKE", + `%${sanitizedSearchParam}%` + ) + } + ] + }; + } + + if (date) { + whereCondition = { + createdAt: { + [Op.between]: [+startOfDay(parseISO(date)), +endOfDay(parseISO(date))] + } + }; + } + + if (updatedAt) { + whereCondition = { + updatedAt: { + [Op.between]: [ + +startOfDay(parseISO(updatedAt)), + +endOfDay(parseISO(updatedAt)) + ] + } + }; + } + + if (withUnreadMessages === "true") { + const user = await ShowUserService(userId); + const userQueueIds = user.queues.map(queue => queue.id); + + whereCondition = { + [Op.or]: [{ userId }, { status: "pending" }], + queueId: { [Op.or]: [userQueueIds, null] }, + unreadMessages: { [Op.gt]: 0 } + }; + } + + if (Array.isArray(tags) && tags.length > 0) { + const ticketsTagFilter: any[] | null = []; + for (let tag of tags) { + const ticketTags = await TicketTag.findAll({ + where: { tagId: tag } + }); + if (ticketTags) { + ticketsTagFilter.push(ticketTags.map(t => t.ticketId)); + } + } + + const ticketsIntersection: number[] = intersection(...ticketsTagFilter); + + whereCondition = { + ...whereCondition, + id: { + [Op.in]: ticketsIntersection + } + }; + } + + if (Array.isArray(users) && users.length > 0) { + const ticketsUserFilter: any[] | null = []; + for (let user of users) { + const ticketUsers = await Ticket.findAll({ + where: { userId: user } + }); + if (ticketUsers) { + ticketsUserFilter.push(ticketUsers.map(t => t.id)); + } + } + + const ticketsIntersection: number[] = intersection(...ticketsUserFilter); + + whereCondition = { + ...whereCondition, + id: { + [Op.in]: ticketsIntersection + } + }; + } + + const limit = 40; + const offset = limit * (+pageNumber - 1); + + whereCondition = { + ...whereCondition, + companyId + }; + + const { count, rows: tickets } = await Ticket.findAndCountAll({ + where: whereCondition, + include: includeCondition, + distinct: true, + limit, + offset, + order: [["updatedAt", "DESC"]], + subQuery: false + }); + + const hasMore = count > offset + tickets.length; + + return { + tickets, + count, + hasMore + }; +}; + +export default ListTicketsService; \ No newline at end of file diff --git a/backend/src/services/TicketServices/ListTicketsServiceKanban.ts b/backend/src/services/TicketServices/ListTicketsServiceKanban.ts new file mode 100644 index 0000000..b96b51c --- /dev/null +++ b/backend/src/services/TicketServices/ListTicketsServiceKanban.ts @@ -0,0 +1,234 @@ +import { Op, fn, where, col, Filterable, Includeable } from "sequelize"; +import { startOfDay, endOfDay, parseISO } from "date-fns"; + +import Ticket from "../../models/Ticket"; +import Contact from "../../models/Contact"; +import Message from "../../models/Message"; +import Queue from "../../models/Queue"; +import User from "../../models/User"; +import ShowUserService from "../UserServices/ShowUserService"; +import Tag from "../../models/Tag"; +import TicketTag from "../../models/TicketTag"; +import { intersection } from "lodash"; +import Whatsapp from "../../models/Whatsapp"; + +interface Request { + searchParam?: string; + pageNumber?: string; + status?: string; + date?: string; + updatedAt?: string; + showAll?: string; + userId: string; + withUnreadMessages?: string; + queueIds: number[]; + tags: number[]; + users: number[]; + companyId: number; +} + +interface Response { + tickets: Ticket[]; + count: number; + hasMore: boolean; +} + +const ListTicketsServiceKanban = async ({ + searchParam = "", + pageNumber = "1", + queueIds, + tags, + users, + status, + date, + updatedAt, + showAll, + userId, + withUnreadMessages, + companyId +}: Request): Promise => { + let whereCondition: Filterable["where"] = { + [Op.or]: [{ userId }, { status: "pending" }], + queueId: { [Op.or]: [queueIds, null] } + }; + let includeCondition: Includeable[]; + + includeCondition = [ + { + model: Contact, + as: "contact", + attributes: ["id", "name", "number", "email"] + }, + { + model: Queue, + as: "queue", + attributes: ["id", "name", "color"] + }, + { + model: User, + as: "user", + attributes: ["id", "name"] + }, + { + model: Tag, + as: "tags", + attributes: ["id", "name", "color"] + }, + { + model: Whatsapp, + as: "whatsapp", + attributes: ["name"] + }, + ]; + + if (showAll === "true") { + whereCondition = { queueId: { [Op.or]: [queueIds, null] } }; + } + + whereCondition = { + ...whereCondition, + status: { [Op.or]: ["pending", "open"] } + }; + + if (searchParam) { + const sanitizedSearchParam = searchParam.toLocaleLowerCase().trim(); + + includeCondition = [ + ...includeCondition, + { + model: Message, + as: "messages", + attributes: ["id", "body"], + where: { + body: where( + fn("LOWER", col("body")), + "LIKE", + `%${sanitizedSearchParam}%` + ) + }, + required: false, + duplicating: false + } + ]; + + whereCondition = { + ...whereCondition, + [Op.or]: [ + { + "$contact.name$": where( + fn("LOWER", col("contact.name")), + "LIKE", + `%${sanitizedSearchParam}%` + ) + }, + { "$contact.number$": { [Op.like]: `%${sanitizedSearchParam}%` } }, + { + "$message.body$": where( + fn("LOWER", col("body")), + "LIKE", + `%${sanitizedSearchParam}%` + ) + } + ] + }; + } + + if (date) { + whereCondition = { + createdAt: { + [Op.between]: [+startOfDay(parseISO(date)), +endOfDay(parseISO(date))] + } + }; + } + + if (updatedAt) { + whereCondition = { + updatedAt: { + [Op.between]: [ + +startOfDay(parseISO(updatedAt)), + +endOfDay(parseISO(updatedAt)) + ] + } + }; + } + + if (withUnreadMessages === "true") { + const user = await ShowUserService(userId); + const userQueueIds = user.queues.map(queue => queue.id); + + whereCondition = { + [Op.or]: [{ userId }, { status: "pending" }], + queueId: { [Op.or]: [userQueueIds, null] }, + unreadMessages: { [Op.gt]: 0 } + }; + } + + if (Array.isArray(tags) && tags.length > 0) { + const ticketsTagFilter: any[] | null = []; + for (let tag of tags) { + const ticketTags = await TicketTag.findAll({ + where: { tagId: tag } + }); + if (ticketTags) { + ticketsTagFilter.push(ticketTags.map(t => t.ticketId)); + } + } + + const ticketsIntersection: number[] = intersection(...ticketsTagFilter); + + whereCondition = { + ...whereCondition, + id: { + [Op.in]: ticketsIntersection + } + }; + } + + if (Array.isArray(users) && users.length > 0) { + const ticketsUserFilter: any[] | null = []; + for (let user of users) { + const ticketUsers = await Ticket.findAll({ + where: { userId: user } + }); + if (ticketUsers) { + ticketsUserFilter.push(ticketUsers.map(t => t.id)); + } + } + + const ticketsIntersection: number[] = intersection(...ticketsUserFilter); + + whereCondition = { + ...whereCondition, + id: { + [Op.in]: ticketsIntersection + } + }; + } + + const limit = 40; + const offset = limit * (+pageNumber - 1); + + whereCondition = { + ...whereCondition, + companyId + }; + + const { count, rows: tickets } = await Ticket.findAndCountAll({ + where: whereCondition, + include: includeCondition, + distinct: true, + limit, + offset, + order: [["updatedAt", "DESC"]], + subQuery: false + }); + const hasMore = count > offset + tickets.length; + + return { + tickets, + count, + hasMore + }; +}; + +export default ListTicketsServiceKanban; \ No newline at end of file diff --git a/backend/src/services/TicketServices/ListTicketsServiceReport.ts b/backend/src/services/TicketServices/ListTicketsServiceReport.ts new file mode 100644 index 0000000..273dbd5 --- /dev/null +++ b/backend/src/services/TicketServices/ListTicketsServiceReport.ts @@ -0,0 +1,114 @@ +/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable camelcase */ +import { QueryTypes } from "sequelize"; +import * as _ from "lodash"; +import sequelize from "../../database"; + +export interface DashboardData { + tickets: any[]; + totalTickets: any; +} + +export interface Params { + searchParam: string; + contactId: string; + whatsappId: string[]; + dateFrom: string; + dateTo: string; + status: string[]; + queueIds: number[]; + tags: number[]; + users: number[]; + userId: string; +} + +export default async function ListTicketsServiceReport( + companyId: string | number, + params: Params, + page: number = 1, + pageSize: number = 20 +): Promise { + const offset = (page - 1) * pageSize; + + const query = ` + select + t.id, + w."name" as "whatsappName", + c."name" as "contactName", + u."name" as "userName", + q."name" as "queueName", + t."lastMessage", + t.uuid, + case t.status + when 'open' then 'ABERTO' + when 'closed' then 'FECHADO' + when 'pending' then 'PENDENTE' + when 'group' then 'GRUPO' + end as "status", + TO_CHAR(t."createdAt", 'DD/MM/YYYY HH24:MI') as "createdAt", + TO_CHAR(tt."finishedAt", 'DD/MM/YYYY HH24:MI') as "closedAt" + from "Tickets" t + LEFT JOIN ( + SELECT DISTINCT ON ("ticketId") * + FROM "TicketTraking" + WHERE "companyId" = ${companyId} + ORDER BY "ticketId", "id" DESC + ) tt ON t.id = tt."ticketId" + inner join "Contacts" c on + t."contactId" = c.id + left join "Whatsapps" w on + t."whatsappId" = w.id + left join "Users" u on + t."userId" = u.id + left join "Queues" q on + t."queueId" = q.id + -- filterPeriod`; + + let where = `where t."companyId" = ${companyId}`; + + if (_.has(params, "dateFrom")) { + where += ` and t."createdAt" >= '${params.dateFrom} 00:00:00'`; + } + + if (_.has(params, "dateTo")) { + where += ` and t."createdAt" <= '${params.dateTo} 23:59:59'`; + } + + if (params.whatsappId !== undefined && params.whatsappId.length > 0) { + where += ` and t."whatsappId" in (${params.whatsappId})`; + } + if (params.users.length > 0) { + where += ` and t."userId" in (${params.users})`; + } + + if (params.queueIds.length > 0) { + where += ` and COALESCE(t."queueId",0) in (${params.queueIds})`; + } + + if (params.status.length > 0) { + where += ` and t."status" in ('${params.status.join("','")}')`; + } + + if (params.contactId !== undefined && params.contactId !== "") { + where += ` and t."contactId" in (${params.contactId})`; + } + + const finalQuery = query.replace("-- filterPeriod", where); + + const totalTicketsQuery = ` + SELECT COUNT(*) as total FROM "Tickets" t + ${where} `; + + const totalTicketsResult = await sequelize.query(totalTicketsQuery, { + type: QueryTypes.SELECT + }); + const totalTickets = totalTicketsResult[0]; + + const paginatedQuery = `${finalQuery} ORDER BY t."createdAt" DESC LIMIT ${pageSize} OFFSET ${offset}`; + + const responseData: any[] = await sequelize.query(paginatedQuery, { + type: QueryTypes.SELECT + }); + + return { tickets: responseData, totalTickets }; +} diff --git a/backend/src/services/TicketServices/ShowTicketFromUUIDService.ts b/backend/src/services/TicketServices/ShowTicketFromUUIDService.ts new file mode 100644 index 0000000..61afebf --- /dev/null +++ b/backend/src/services/TicketServices/ShowTicketFromUUIDService.ts @@ -0,0 +1,51 @@ +import Ticket from "../../models/Ticket"; +import AppError from "../../errors/AppError"; +import Contact from "../../models/Contact"; +import User from "../../models/User"; +import Queue from "../../models/Queue"; +import Tag from "../../models/Tag"; +import Whatsapp from "../../models/Whatsapp"; + +const ShowTicketUUIDService = async (uuid: string): Promise => { + const ticket = await Ticket.findOne({ + where: { + uuid + }, + include: [ + { + model: Contact, + as: "contact", + attributes: ["id", "name", "number", "email", "profilePicUrl"], + include: ["extraInfo"] + }, + { + model: User, + as: "user", + attributes: ["id", "name"] + }, + { + model: Queue, + as: "queue", + attributes: ["id", "name", "color"] + }, + { + model: Whatsapp, + as: "whatsapp", + attributes: ["name"] + }, + { + model: Tag, + as: "tags", + attributes: ["id", "name", "color"] + } + ] + }); + + if (!ticket) { + throw new AppError("ERR_NO_TICKET_FOUND", 404); + } + + return ticket; +}; + +export default ShowTicketUUIDService; diff --git a/backend/src/services/TicketServices/ShowTicketService.ts b/backend/src/services/TicketServices/ShowTicketService.ts new file mode 100644 index 0000000..68d10d3 --- /dev/null +++ b/backend/src/services/TicketServices/ShowTicketService.ts @@ -0,0 +1,57 @@ +import Ticket from "../../models/Ticket"; +import AppError from "../../errors/AppError"; +import Contact from "../../models/Contact"; +import User from "../../models/User"; +import Queue from "../../models/Queue"; +import Tag from "../../models/Tag"; +import Whatsapp from "../../models/Whatsapp"; +import Prompt from "../../models/Prompt"; + +const ShowTicketService = async ( + id: string | number, + companyId: number +): Promise => { + const ticket = await Ticket.findByPk(id, { + include: [ + { + model: Contact, + as: "contact", + attributes: ["id", "name", "number", "email", "profilePicUrl","messengerId", "instagramId"], + include: ["extraInfo"] + }, + { + model: User, + as: "user", + attributes: ["id", "name"] + }, + { + model: Queue, + as: "queue", + attributes: ["id", "name", "color"], + include: ["prompt", "queueIntegrations"] + }, + { + model: Whatsapp, + as: "whatsapp", + attributes: ["name","type"] + }, + { + model: Tag, + as: "tags", + attributes: ["id", "name", "color"] + } + ] + }); + + if (ticket?.companyId !== companyId) { + throw new AppError("Não é possível consultar registros de outra empresa"); + } + + if (!ticket) { + throw new AppError("ERR_NO_TICKET_FOUND", 404); + } + + return ticket; +}; + +export default ShowTicketService; diff --git a/backend/src/services/TicketServices/UpdateTicketService.ts b/backend/src/services/TicketServices/UpdateTicketService.ts new file mode 100644 index 0000000..a47e7bb --- /dev/null +++ b/backend/src/services/TicketServices/UpdateTicketService.ts @@ -0,0 +1,311 @@ +import moment from "moment"; +import * as Sentry from "@sentry/node"; +import CheckContactOpenTickets from "../../helpers/CheckContactOpenTickets"; +import SetTicketMessagesAsRead from "../../helpers/SetTicketMessagesAsRead"; +import { getIO } from "../../libs/socket"; +import Ticket from "../../models/Ticket"; +import Setting from "../../models/Setting"; +import Queue from "../../models/Queue"; +import ShowTicketService from "./ShowTicketService"; +import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService"; +import SendWhatsAppMessage from "../WbotServices/SendWhatsAppMessage"; +import FindOrCreateATicketTrakingService from "./FindOrCreateATicketTrakingService"; +import GetTicketWbot from "../../helpers/GetTicketWbot"; +import { verifyMessage } from "../WbotServices/wbotMessageListener"; +import ListSettingsServiceOne from "../SettingServices/ListSettingsServiceOne"; //NOVO PLW DESIGN// +import ShowUserService from "../UserServices/ShowUserService"; //NOVO PLW DESIGN// +import { isNil } from "lodash"; +import Whatsapp from "../../models/Whatsapp"; +import { Op } from "sequelize"; +import AppError from "../../errors/AppError"; + + +interface TicketData { + status?: string; + userId?: number | null; + queueId?: number | null; + chatbot?: boolean; + queueOptionId?: number; + whatsappId?: string; + useIntegration?: boolean; + integrationId?: number | null; + promptId?: number | null; + lastMessage?: string; +} + +interface Request { + ticketData: TicketData; + ticketId: string | number; + companyId: number; +} + +interface Response { + ticket: Ticket; + oldStatus: string; + oldUserId: number | undefined; +} + +const UpdateTicketService = async ({ + ticketData, + ticketId, + companyId +}: Request): Promise => { + + try { + let { status } = ticketData; + let { queueId, userId, whatsappId, lastMessage = null } = ticketData; + let chatbot: boolean | null = ticketData.chatbot || false; + let queueOptionId: number | null = ticketData.queueOptionId || null; + let promptId: number | null = ticketData.promptId || null; + let useIntegration: boolean | null = ticketData.useIntegration || false; + let integrationId: number | null = ticketData.integrationId || null; + + console.log("ticketData", ticketData); + + const io = getIO(); + + const ticket = await ShowTicketService(ticketId, companyId); + const ticketTraking = await FindOrCreateATicketTrakingService({ + ticketId, + companyId, + whatsappId: ticket.whatsappId + }); + + if (isNil(whatsappId)) { + whatsappId = ticket.whatsappId?.toString(); + } + + await SetTicketMessagesAsRead(ticket); + + const oldStatus = ticket.status; + const oldUserId = ticket.user?.id; + const oldQueueId = ticket.queueId; + + if (oldStatus === "closed" || Number(whatsappId) !== ticket.whatsappId) { + // let otherTicket = await Ticket.findOne({ + // where: { + // contactId: ticket.contactId, + // status: { [Op.or]: ["open", "pending", "group"] }, + // whatsappId + // } + // }); + // if (otherTicket) { + // otherTicket = await ShowTicketService(otherTicket.id, companyId) + + // await ticket.update({status: "closed"}) + + // io.to(oldStatus).emit(`company-${companyId}-ticket`, { + // action: "delete", + // ticketId: ticket.id + // }); + + // return { ticket: otherTicket, oldStatus, oldUserId } + // } + await CheckContactOpenTickets(ticket.contact.id, whatsappId); + chatbot = null; + queueOptionId = null; + } + + if (status === "closed") { + const { complationMessage, ratingMessage } = ticket.whatsappId + ? await ShowWhatsAppService(ticket.whatsappId, companyId) + : { complationMessage: null, ratingMessage: null }; + + const settingEvaluation = await ListSettingsServiceOne({ + companyId: companyId, + key: "userRating" + }); + + // Envia a mensagem de avaliação apenas se o ticket não estiver em status 'pendente' + if ( + ticket.status !== "pending" && // Adiciona a verificação para evitar avaliação em status pendente + !ticket.contact.isGroup && + !ticket.contact.disableBot && + settingEvaluation?.value === "enabled" + ) { + if (ticketTraking.ratingAt == null && ticketTraking.userId !== null) { + const bodyRatingMessage = `${ + ratingMessage ? ratingMessage + "\n\n" : "" + }Digite de 1 a 5 para qualificar nosso atendimento:\n\n*1* - 😞 _Péssimo_\n*2* - 😕 _Ruim_\n*3* - 😐 _Neutro_\n*4* - 🙂 _Bom_\n*5* - 😊 _Ótimo_`; + + await SendWhatsAppMessage({ body: bodyRatingMessage, ticket }); + + await ticketTraking.update({ + ratingAt: moment().toDate() + }); + + // Remove o ticket da lista de abertos + io.to(`company-${ticket.companyId}-open`) + .to(`queue-${ticket.queueId}-open`) + .to(ticketId.toString()) + .emit(`company-${ticket.companyId}-ticket`, { + action: "delete", + ticketId: ticket.id + }); + + return { ticket, oldStatus, oldUserId }; + } + + ticketTraking.ratingAt = moment().toDate(); + ticketTraking.rated = false; + } else { + // Envia apenas a mensagem de finalização se estiver configurada + ticketTraking.finishedAt = moment().toDate(); + + if ( + !ticket.contact.isGroup && + !ticket.contact.disableBot && + !isNil(complationMessage) && + complationMessage !== "" + ) { + const body = `\u200e${complationMessage}`; + await SendWhatsAppMessage({ body, ticket }); + } + } + + await ticket.update({ + promptId: null, + integrationId: null, + useIntegration: false, + typebotStatus: false, + typebotSessionId: null + }); + + ticketTraking.finishedAt = moment().toDate(); + ticketTraking.whatsappId = ticket.whatsappId; + ticketTraking.userId = ticket.userId; + +} + + if (queueId !== undefined && queueId !== null) { + ticketTraking.queuedAt = moment().toDate(); + } + + const settingsTransfTicket = await ListSettingsServiceOne({ companyId: companyId, key: "sendMsgTransfTicket" }); + + if (settingsTransfTicket?.value === "enabled") { + // Mensagem de transferencia da FILA + if (oldQueueId !== queueId && oldUserId === userId && !isNil(oldQueueId) && !isNil(queueId)) { + + const queue = await Queue.findByPk(queueId); + const wbot = await GetTicketWbot(ticket); + const msgtxt = "*Mensagem automática*:\nVocê foi transferido para o departamento *" + queue?.name + "*\naguarde, já vamos te atender!"; + + const queueChangedMessage = await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + { + text: msgtxt + } + ); + await verifyMessage(queueChangedMessage, ticket, ticket.contact); + } + else + // Mensagem de transferencia do ATENDENTE + if (oldUserId !== userId && oldQueueId === queueId && !isNil(oldUserId) && !isNil(userId)) { + const wbot = await GetTicketWbot(ticket); + const nome = await ShowUserService(ticketData.userId); + const msgtxt = "*Mensagem automática*:\nFoi transferido para o atendente *" + nome.name + "*\naguarde, já vamos te atender!"; + + const queueChangedMessage = await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + { + text: msgtxt + } + ); + await verifyMessage(queueChangedMessage, ticket, ticket.contact); + } + else + // Mensagem de transferencia do ATENDENTE e da FILA + if (oldUserId !== userId && !isNil(oldUserId) && !isNil(userId) && oldQueueId !== queueId && !isNil(oldQueueId) && !isNil(queueId)) { + const wbot = await GetTicketWbot(ticket); + const queue = await Queue.findByPk(queueId); + const nome = await ShowUserService(ticketData.userId); + const msgtxt = "*Mensagem automática*:\nVocê foi transferido para o departamento *" + queue?.name + "* e contará com a presença de *" + nome.name + "*\naguarde, já vamos te atender!"; + + const queueChangedMessage = await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + { + text: msgtxt + } + ); + await verifyMessage(queueChangedMessage, ticket, ticket.contact); + } else + if (oldUserId !== undefined && isNil(userId) && oldQueueId !== queueId && !isNil(queueId)) { + + const queue = await Queue.findByPk(queueId); + const wbot = await GetTicketWbot(ticket); + const msgtxt = "*Mensagem automática*:\nVocê foi transferido para o departamento *" + queue?.name + "*\naguarde, já vamos te atender!"; + + const queueChangedMessage = await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + { + text: msgtxt + } + ); + await verifyMessage(queueChangedMessage, ticket, ticket.contact); + } + } + + await ticket.update({ + status, + queueId, + userId, + whatsappId, + chatbot, + queueOptionId, + lastMessage: lastMessage !== null ? lastMessage : ticket.lastMessage + }); + + await ticket.reload(); + + if (status === "pending") { + await ticketTraking.update({ + whatsappId, + queuedAt: moment().toDate(), + startedAt: null, + userId: null + }); + } + + if (status === "open") { + await ticketTraking.update({ + startedAt: moment().toDate(), + ratingAt: null, + rated: false, + whatsappId, + userId: ticket.userId + }); + } + + await ticketTraking.save(); + + if (ticket.status !== oldStatus || ticket.user?.id !== oldUserId) { + + io.to(`company-${companyId}-${oldStatus}`) + .to(`queue-${ticket.queueId}-${oldStatus}`) + .to(`user-${oldUserId}`) + .emit(`company-${companyId}-ticket`, { + action: "delete", + ticketId: ticket.id + }); + } + + io.to(`company-${companyId}-${ticket.status}`) + .to(`company-${companyId}-notification`) + .to(`queue-${ticket.queueId}-${ticket.status}`) + .to(`queue-${ticket.queueId}-notification`) + .to(ticketId.toString()) + .to(`user-${ticket?.userId}`) + .to(`user-${oldUserId}`) + .emit(`company-${companyId}-ticket`, { + action: "update", + ticket + }); + + return { ticket, oldStatus, oldUserId }; + } catch (err) { + Sentry.captureException(err); + } +}; + +export default UpdateTicketService; diff --git a/backend/src/services/TypebotServices/typebotListener.ts b/backend/src/services/TypebotServices/typebotListener.ts new file mode 100644 index 0000000..30147f3 --- /dev/null +++ b/backend/src/services/TypebotServices/typebotListener.ts @@ -0,0 +1,413 @@ +import axios from "axios"; +import Ticket from "../../models/Ticket"; +import QueueIntegrations from "../../models/QueueIntegrations"; +import { WASocket, delay, proto } from "@whiskeysockets/baileys"; +import { getBodyMessage } from "../WbotServices/wbotMessageListener"; +import { logger } from "../../utils/logger"; +import { isNil } from "lodash"; +import UpdateTicketService from "../TicketServices/UpdateTicketService"; + + +type Session = WASocket & { + id?: number; +}; + +interface Request { + wbot: Session; + msg: proto.IWebMessageInfo; + ticket: Ticket; + typebot: QueueIntegrations; +} + + +const typebotListener = async ({ + wbot, + msg, + ticket, + typebot +}: Request): Promise => { + + if (msg.key.remoteJid === 'status@broadcast') return; + + const { urlN8N: url, + typebotExpires, + typebotKeywordFinish, + typebotKeywordRestart, + typebotUnknownMessage, + typebotSlug, + typebotDelayMessage, + typebotRestartMessage + } = typebot; + + const number = msg.key.remoteJid.replace(/\D/g, ''); + + let body = getBodyMessage(msg); + + async function createSession(msg, typebot, number) { + try { + const id = Math.floor(Math.random() * 10000000000).toString(); + + const reqData = JSON.stringify({ + "isStreamEnabled": true, + "message": "string", + "resultId": "string", + "isOnlyRegistering": false, + "prefilledVariables": { + "number": number, + "pushName": msg.pushName || "" + }, + }); + + const config = { + method: 'post', + maxBodyLength: Infinity, + url: `${url}/api/v1/typebots/${typebotSlug}/startChat`, + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + data: reqData + }; + + const request = await axios.request(config); + + return request.data; + + } catch (err) { + logger.info("Erro ao criar sessão do typebot: ", err) + throw err; + } + } + + + let sessionId + let dataStart + let status = false; + try { + const dataLimite = new Date() + dataLimite.setMinutes(dataLimite.getMinutes() - Number(typebotExpires)); + + + if (typebotExpires > 0 && ticket.updatedAt < dataLimite) { + await ticket.update({ + typebotSessionId: null, + isBot: true + }); + + await ticket.reload(); + } + + if (isNil(ticket.typebotSessionId)) { + dataStart = await createSession(msg, typebot, number); + sessionId = dataStart.sessionId + status = true; + await ticket.update({ + typebotSessionId: sessionId, + typebotStatus: true, + useIntegration: true, + integrationId: typebot.id + }) + } else { + sessionId = ticket.typebotSessionId; + status = ticket.typebotStatus; + } + + if (!status) return; + + //let body = getConversationMessage(msg); + + + if (body !== typebotKeywordFinish && body !== typebotKeywordRestart) { + let requestContinue + let messages + let input + if (dataStart?.messages.length === 0 || dataStart === undefined) { + const reqData = JSON.stringify({ + "message": body + }); + + let config = { + method: 'post', + maxBodyLength: Infinity, + url: `${url}/api/v1/sessions/${sessionId}/continueChat`, + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + data: reqData + }; + requestContinue = await axios.request(config); + messages = requestContinue.data?.messages; + input = requestContinue.data?.input; + } else { + messages = dataStart?.messages; + input = dataStart?.input; + } + + if (messages?.length === 0) { + await wbot.sendMessage(`${number}@c.us`, { text: typebotUnknownMessage }); + } else { + for (const message of messages) { + if (message.type === 'text') { + let formattedText = ''; + let linkPreview = false; + for (const richText of message.content.richText) { + for (const element of richText.children) { + let text = ''; + + if (element.text) { + text = element.text; + } + if (element.type && element.children) { + for (const subelement of element.children) { + let text = ''; + + if (subelement.text) { + text = subelement.text; + } + + if (subelement.type && subelement.children) { + for (const subelement2 of subelement.children) { + let text = ''; + + if (subelement2.text) { + text = subelement2.text; + } + + if (subelement2.bold) { + text = `*${text}*`; + } + if (subelement2.italic) { + text = `_${text}_`; + } + if (subelement2.underline) { + text = `~${text}~`; + } + if (subelement2.url) { + const linkText = subelement2.children[0].text; + text = `[${linkText}](${subelement2.url})`; + linkPreview = true; + } + formattedText += text; + } + } + if (subelement.bold) { + text = `*${text}*`; + } + if (subelement.italic) { + text = `_${text}_`; + } + if (subelement.underline) { + text = `~${text}~`; + } + if (subelement.url) { + const linkText = subelement.children[0].text; + text = `[${linkText}](${subelement.url})`; + linkPreview = true; + } + formattedText += text; + } + } + + if (element.bold) { + text = `*${text}*` + } + if (element.italic) { + text = `_${text}_`; + } + if (element.underline) { + text = `~${text}~`; + } + + if (element.url) { + const linkText = element.children[0].text; + text = `[${linkText}](${element.url})`; + linkPreview = true; + } + + formattedText += text; + } + formattedText += '\n'; + } + formattedText = formattedText.replace('**', '').replace(/\n$/, ''); + + if (formattedText === "Invalid message. Please, try again.") { + formattedText = typebotUnknownMessage; + } + + if (formattedText.startsWith("#")) { + let gatilho = formattedText.replace("#", ""); + + try { + let jsonGatilho = JSON.parse(gatilho); + + if (jsonGatilho.stopBot && isNil(jsonGatilho.userId) && isNil(jsonGatilho.queueId)) { + await ticket.update({ + useIntegration: false, + isBot: false + }) + + return; + } + if (!isNil(jsonGatilho.queueId) && jsonGatilho.queueId > 0 && isNil(jsonGatilho.userId)) { + await UpdateTicketService({ + ticketData: { + queueId: jsonGatilho.queueId, + chatbot: false, + useIntegration: false, + integrationId: null + }, + ticketId: ticket.id, + companyId: ticket.companyId + }) + + return; + } + + if (!isNil(jsonGatilho.queueId) && jsonGatilho.queueId > 0 && !isNil(jsonGatilho.userId) && jsonGatilho.userId > 0) { + await UpdateTicketService({ + ticketData: { + queueId: jsonGatilho.queueId, + userId: jsonGatilho.userId, + chatbot: false, + useIntegration: false, + integrationId: null + }, + ticketId: ticket.id, + companyId: ticket.companyId + }) + + return; + } + } catch (err) { + throw err + } + } + + await wbot.presenceSubscribe(msg.key.remoteJid) + //await delay(2000) + await wbot.sendPresenceUpdate('composing', msg.key.remoteJid) + await delay(typebotDelayMessage) + await wbot.sendPresenceUpdate('paused', msg.key.remoteJid) + + + await wbot.sendMessage(msg.key.remoteJid, { text: formattedText }); + } + + if (message.type === 'audio') { + await wbot.presenceSubscribe(msg.key.remoteJid) + //await delay(2000) + await wbot.sendPresenceUpdate('composing', msg.key.remoteJid) + await delay(typebotDelayMessage) + await wbot.sendPresenceUpdate('paused', msg.key.remoteJid) + const media = { + audio: { + url: message.content.url, + mimetype: 'audio/mp4', + ptt: true + }, + } + await wbot.sendMessage(msg.key.remoteJid, media); + + } + + // if (message.type === 'embed') { + // await wbot.presenceSubscribe(msg.key.remoteJid) + // //await delay(2000) + // await wbot.sendPresenceUpdate('composing', msg.key.remoteJid) + // await delay(typebotDelayMessage) + // await wbot.sendPresenceUpdate('paused', msg.key.remoteJid) + // const media = { + + // document: { url: message.content.url }, + // mimetype: 'application/pdf', + // caption: "" + + // } + // await wbot.sendMessage(msg.key.remoteJid, media); + // } + + if (message.type === 'image') { + await wbot.presenceSubscribe(msg.key.remoteJid) + //await delay(2000) + await wbot.sendPresenceUpdate('composing', msg.key.remoteJid) + await delay(typebotDelayMessage) + await wbot.sendPresenceUpdate('paused', msg.key.remoteJid) + const media = { + image: { + url: message.content.url, + }, + + } + await wbot.sendMessage(msg.key.remoteJid, media); + } + + // if (message.type === 'video' ) { + // await wbot.presenceSubscribe(msg.key.remoteJid) + // //await delay(2000) + // await wbot.sendPresenceUpdate('composing', msg.key.remoteJid) + // await delay(typebotDelayMessage) + // await wbot.sendPresenceUpdate('paused', msg.key.remoteJid) + // const media = { + // video: { + // url: message.content.url, + // }, + + // } + // await wbot.sendMessage(msg.key.remoteJid, media); + // } + } + if (input) { + if (input.type === 'choice input') { + let formattedText = ''; + const items = input.items; + for (const item of items) { + formattedText += `▶️ ${item.content}\n`; + } + formattedText = formattedText.replace(/\n$/, ''); + await wbot.presenceSubscribe(msg.key.remoteJid) + //await delay(2000) + await wbot.sendPresenceUpdate('composing', msg.key.remoteJid) + await delay(typebotDelayMessage) + await wbot.sendPresenceUpdate('paused', msg.key.remoteJid) + await wbot.sendMessage(msg.key.remoteJid, { text: formattedText }); + + } + } + } + } + if (body === typebotKeywordRestart) { + await ticket.update({ + isBot: true, + typebotSessionId: null + + }) + + await ticket.reload(); + + await wbot.sendMessage(`${number}@c.us`, { text: typebotRestartMessage }) + + } + if (body === typebotKeywordFinish) { + await UpdateTicketService({ + ticketData: { + status: "closed", + useIntegration: false, + integrationId: null + }, + ticketId: ticket.id, + companyId: ticket.companyId + }) + + return; + } + } catch (error) { + logger.info("Error on typebotListener: ", error); + await ticket.update({ + typebotSessionId: null + }) + throw error; + } +} + +export default typebotListener; diff --git a/backend/src/services/UserServices/AuthUserService.ts b/backend/src/services/UserServices/AuthUserService.ts new file mode 100644 index 0000000..463adb4 --- /dev/null +++ b/backend/src/services/UserServices/AuthUserService.ts @@ -0,0 +1,61 @@ +import User from "../../models/User"; +import AppError from "../../errors/AppError"; +import { + createAccessToken, + createRefreshToken +} from "../../helpers/CreateTokens"; +import { SerializeUser } from "../../helpers/SerializeUser"; +import Queue from "../../models/Queue"; +import Company from "../../models/Company"; +import Setting from "../../models/Setting"; + +interface SerializedUser { + id: number; + name: string; + email: string; + profile: string; + queues: Queue[]; + companyId: number; +} + +interface Request { + email: string; + password: string; +} + +interface Response { + serializedUser: SerializedUser; + token: string; + refreshToken: string; +} + +const AuthUserService = async ({ + email, + password +}: Request): Promise => { + const user = await User.findOne({ + where: { email }, + include: ["queues", { model: Company, include: [{ model: Setting }] }] + }); + + if (!user) { + throw new AppError("ERR_INVALID_CREDENTIALS", 401); + } + + if (!(await user.checkPassword(password))) { + throw new AppError("ERR_INVALID_CREDENTIALS", 401); + } + + const token = createAccessToken(user); + const refreshToken = createRefreshToken(user); + + const serializedUser = await SerializeUser(user); + + return { + serializedUser, + token, + refreshToken + }; +}; + +export default AuthUserService; diff --git a/backend/src/services/UserServices/CreateUserService.ts b/backend/src/services/UserServices/CreateUserService.ts new file mode 100644 index 0000000..5056d73 --- /dev/null +++ b/backend/src/services/UserServices/CreateUserService.ts @@ -0,0 +1,110 @@ +import * as Yup from "yup"; + +import AppError from "../../errors/AppError"; +import { SerializeUser } from "../../helpers/SerializeUser"; +import User from "../../models/User"; +import Plan from "../../models/Plan"; +import Company from "../../models/Company"; + +interface Request { + email: string; + password: string; + name: string; + queueIds?: number[]; + companyId?: number; + profile?: string; + whatsappId?: number; + allTicket?:string; + whatsappNumber?:string; +} + +interface Response { + email: string; + name: string; + id: number; + profile: string; +} + +const CreateUserService = async ({ + email, + password, + name, + queueIds = [], + companyId, + profile = "admin", + whatsappId, + allTicket, + whatsappNumber +}: Request): Promise => { + if (companyId !== undefined) { + const company = await Company.findOne({ + where: { + id: companyId + }, + include: [{ model: Plan, as: "plan" }] + }); + + if (company !== null) { + const usersCount = await User.count({ + where: { + companyId + } + }); + + if (usersCount >= company.plan.users) { + throw new AppError( + `Número máximo de usuários já alcançado: ${usersCount}` + ); + } + } + } + + const schema = Yup.object().shape({ + name: Yup.string().required().min(2), + email: Yup.string() + .email() + .required() + .test( + "Check-email", + "An user with this email already exists.", + async value => { + if (!value) return false; + const emailExists = await User.findOne({ + where: { email: value } + }); + return !emailExists; + } + ), + password: Yup.string().required().min(5) + }); + + try { + await schema.validate({ email, password, name }); + } catch (err) { + throw new AppError(err.message); + } + + const user = await User.create( + { + email, + password, + name, + companyId, + profile, + whatsappId: whatsappId || null, + allTicket, + whatsappNumber + }, + { include: ["queues", "company"] } + ); + + await user.$set("queues", queueIds); + + await user.reload(); + + const serializedUser = SerializeUser(user); + + return serializedUser; +}; + +export default CreateUserService; diff --git a/backend/src/services/UserServices/DeleteUserService.ts b/backend/src/services/UserServices/DeleteUserService.ts new file mode 100644 index 0000000..96a9a79 --- /dev/null +++ b/backend/src/services/UserServices/DeleteUserService.ts @@ -0,0 +1,29 @@ +import User from "../../models/User"; +import AppError from "../../errors/AppError"; +import Ticket from "../../models/Ticket"; +import UpdateDeletedUserOpenTicketsStatus from "../../helpers/UpdateDeletedUserOpenTicketsStatus"; + +const DeleteUserService = async ( + id: string | number, + companyId: number +): Promise => { + const user = await User.findOne({ + where: { id } + }); + + if (!user) { + throw new AppError("ERR_NO_USER_FOUND", 404); + } + + const userOpenTickets: Ticket[] = await user.$get("tickets", { + where: { status: "open" } + }); + + if (userOpenTickets.length > 0) { + UpdateDeletedUserOpenTicketsStatus(userOpenTickets, companyId); + } + + await user.destroy(); +}; + +export default DeleteUserService; diff --git a/backend/src/services/UserServices/ListUsersService.ts b/backend/src/services/UserServices/ListUsersService.ts new file mode 100644 index 0000000..519ad59 --- /dev/null +++ b/backend/src/services/UserServices/ListUsersService.ts @@ -0,0 +1,64 @@ +import { Sequelize, Op } from "sequelize"; +import Queue from "../../models/Queue"; +import Company from "../../models/Company"; +import User from "../../models/User"; + +interface Request { + searchParam?: string; + pageNumber?: string | number; + profile?: string; + companyId?: number; +} + +interface Response { + users: User[]; + count: number; + hasMore: boolean; +} + +const ListUsersService = async ({ + searchParam = "", + pageNumber = "1", + companyId +}: Request): Promise => { + const whereCondition = { + [Op.or]: [ + { + "$User.name$": Sequelize.where( + Sequelize.fn("LOWER", Sequelize.col("User.name")), + "LIKE", + `%${searchParam.toLowerCase()}%` + ) + }, + { email: { [Op.like]: `%${searchParam.toLowerCase()}%` } } + ], + companyId: { + [Op.eq]: companyId + } + }; + + const limit = 20; + const offset = limit * (+pageNumber - 1); + + const { count, rows: users } = await User.findAndCountAll({ + where: whereCondition, + attributes: ["name", "id", "email", "companyId", "profile", "createdAt", "online"], + limit, + offset, + order: [["createdAt", "DESC"]], + include: [ + { model: Queue, as: "queues", attributes: ["id", "name", "color"] }, + { model: Company, as: "company", attributes: ["id", "name"] } + ] + }); + + const hasMore = count > offset + users.length; + + return { + users, + count, + hasMore + }; +}; + +export default ListUsersService; diff --git a/backend/src/services/UserServices/ShowUserService.ts b/backend/src/services/UserServices/ShowUserService.ts new file mode 100644 index 0000000..bb29721 --- /dev/null +++ b/backend/src/services/UserServices/ShowUserService.ts @@ -0,0 +1,32 @@ +import User from "../../models/User"; +import AppError from "../../errors/AppError"; +import Queue from "../../models/Queue"; +import Company from "../../models/Company"; + +const ShowUserService = async (id: string | number): Promise => { + const user = await User.findByPk(id, { + attributes: [ + "name", + "id", + "email", + "companyId", + "profile", + "super", + "tokenVersion", + "whatsappId", + "allTicket" + ], + include: [ + { model: Queue, as: "queues", attributes: ["id", "name", "color"] }, + { model: Company, as: "company", attributes: ["id", "name", "dueDate"] } + ] + }); + + if (!user) { + throw new AppError("ERR_NO_USER_FOUND", 404); + } + + return user; +}; + +export default ShowUserService; diff --git a/backend/src/services/UserServices/SimpleListService.ts b/backend/src/services/UserServices/SimpleListService.ts new file mode 100644 index 0000000..a484d4f --- /dev/null +++ b/backend/src/services/UserServices/SimpleListService.ts @@ -0,0 +1,28 @@ +import User from "../../models/User"; +import AppError from "../../errors/AppError"; +import Queue from "../../models/Queue"; + +interface Params { + companyId: string | number; +} + +const SimpleListService = async ({ companyId }: Params): Promise => { + const users = await User.findAll({ + where: { + companyId + }, + attributes: ["name", "id", "email"], + include: [ + { model: Queue, as: 'queues' } + ], + order: [["id", "ASC"]] + }); + + if (!users) { + throw new AppError("ERR_NO_USER_FOUND", 404); + } + + return users; +}; + +export default SimpleListService; diff --git a/backend/src/services/UserServices/UpdateUserService.ts b/backend/src/services/UserServices/UpdateUserService.ts new file mode 100644 index 0000000..23fefa5 --- /dev/null +++ b/backend/src/services/UserServices/UpdateUserService.ts @@ -0,0 +1,93 @@ +import * as Yup from "yup"; + +import AppError from "../../errors/AppError"; +import ShowUserService from "./ShowUserService"; +import Company from "../../models/Company"; +import User from "../../models/User"; + +interface UserData { + email?: string; + password?: string; + name?: string; + profile?: string; + companyId?: number; + queueIds?: number[]; + whatsappId?: number; + allTicket?: string; + whatsappNumber?: string; +} + +interface Request { + userData: UserData; + userId: string | number; + companyId: number; + requestUserId: number; +} + +interface Response { + id: number; + name: string; + email: string; + profile: string; +} + +const UpdateUserService = async ({ + userData, + userId, + companyId, + requestUserId +}: Request): Promise => { + const user = await ShowUserService(userId); + + const requestUser = await User.findByPk(requestUserId); + + if (requestUser.super === false && userData.companyId !== companyId) { + throw new AppError("O usuário não pertence à esta empresa"); + } + + const schema = Yup.object().shape({ + name: Yup.string().min(2), + email: Yup.string().email(), + profile: Yup.string(), + password: Yup.string(), + allTicket: Yup.string() + }); + + const { email, password, profile, name, queueIds = [], whatsappId, allTicket, whatsappNumber } = userData; + + try { + await schema.validate({ email, password, profile, name, allTicket }); + } catch (err: any) { + throw new AppError(err.message); + } + + await user.update({ + email, + password, + profile, + name, + whatsappId: whatsappId || null, + allTicket, + whatsappNumber + }); + + await user.$set("queues", queueIds); + + await user.reload(); + + const company = await Company.findByPk(user.companyId); + + const serializedUser = { + id: user.id, + name: user.name, + email: user.email, + profile: user.profile, + companyId: user.companyId, + company, + queues: user.queues + }; + + return serializedUser; +}; + +export default UpdateUserService; diff --git a/backend/src/services/WbotServices/CheckIsValidContact.ts b/backend/src/services/WbotServices/CheckIsValidContact.ts new file mode 100644 index 0000000..1b567b0 --- /dev/null +++ b/backend/src/services/WbotServices/CheckIsValidContact.ts @@ -0,0 +1,26 @@ +import AppError from "../../errors/AppError"; +import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp"; +import { getWbot } from "../../libs/wbot"; + +const CheckIsValidContact = async ( + number: string, + companyId: number +): Promise => { + const defaultWhatsapp = await GetDefaultWhatsApp(companyId); + + const wbot = getWbot(defaultWhatsapp.id); + + try { + const isValidNumber = await wbot.onWhatsApp(`${number}`); + if (!isValidNumber) { + throw new AppError("invalidNumber"); + } + } catch (err: any) { + if (err.message === "invalidNumber") { + throw new AppError("ERR_WAPP_INVALID_CONTACT"); + } + throw new AppError("ERR_WAPP_CHECK_CONTACT"); + } +}; + +export default CheckIsValidContact; diff --git a/backend/src/services/WbotServices/CheckNumber.ts b/backend/src/services/WbotServices/CheckNumber.ts new file mode 100644 index 0000000..f700daa --- /dev/null +++ b/backend/src/services/WbotServices/CheckNumber.ts @@ -0,0 +1,33 @@ +import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp"; +import { getWbot } from "../../libs/wbot"; +import { logger } from "../../utils/logger"; + +interface IOnWhatsapp { + jid: string; + exists: boolean; +} + +const checker = async (number: string, wbot: any) => { + const [validNumber] = await wbot.onWhatsApp(`${number}@s.whatsapp.net`); + + logger.info(validNumber); + + return validNumber; +}; + +const CheckContactNumber = async ( + number: string, + companyId: number +): Promise => { + const defaultWhatsapp = await GetDefaultWhatsApp(companyId); + + const wbot = getWbot(defaultWhatsapp.id); + const isNumberExit = await checker(number, wbot); + + if (!isNumberExit.exists) { + throw new Error("ERR_CHECK_NUMBER"); + } + return isNumberExit; +}; + +export default CheckContactNumber; diff --git a/backend/src/services/WbotServices/DeleteWhatsAppMessage.ts b/backend/src/services/WbotServices/DeleteWhatsAppMessage.ts new file mode 100644 index 0000000..6c9497a --- /dev/null +++ b/backend/src/services/WbotServices/DeleteWhatsAppMessage.ts @@ -0,0 +1,51 @@ +import { proto, WASocket } from "@whiskeysockets/baileys"; +import WALegacySocket from "@whiskeysockets/baileys" +import AppError from "../../errors/AppError"; +import GetTicketWbot from "../../helpers/GetTicketWbot"; +import GetWbotMessage from "../../helpers/GetWbotMessage"; +import Message from "../../models/Message"; +import Ticket from "../../models/Ticket"; + +const DeleteWhatsAppMessage = async (messageId: string): Promise => { + const message = await Message.findByPk(messageId, { + include: [ + { + model: Ticket, + as: "ticket", + include: ["contact"] + } + ] + }); + + if (!message) { + throw new AppError("No message found with this ID."); + } + + const { ticket } = message; + + const messageToDelete = await GetWbotMessage(ticket, messageId); + + try { + const wbot = await GetTicketWbot(ticket); + const messageDelete = messageToDelete as proto.WebMessageInfo; + + const menssageDelete = messageToDelete as Message; + + await (wbot as WASocket).sendMessage(menssageDelete.remoteJid, { + delete: { + id: menssageDelete.id, + remoteJid: menssageDelete.remoteJid, + participant: menssageDelete.participant, + fromMe: menssageDelete.fromMe + } + }); + + } catch (err) { + throw new AppError("ERR_DELETE_WAPP_MSG"); + } + await message.update({ isDeleted: true }); + + return message; +}; + +export default DeleteWhatsAppMessage; diff --git a/backend/src/services/WbotServices/EditWhatsAppMessage.ts b/backend/src/services/WbotServices/EditWhatsAppMessage.ts new file mode 100644 index 0000000..b1d05ae --- /dev/null +++ b/backend/src/services/WbotServices/EditWhatsAppMessage.ts @@ -0,0 +1,54 @@ +import AppError from "../../errors/AppError"; +import GetTicketWbot from "../../helpers/GetTicketWbot"; +import Message from "../../models/Message"; +import Ticket from "../../models/Ticket"; + +import formatBody from "../../helpers/Mustache"; + +interface Request { + messageId: string; + body: string; +} + +const EditWhatsAppMessage = async ({ + messageId, + body, +}: Request): Promise<{ ticket: Ticket , message: Message}> => { + + const message = await Message.findByPk(messageId, { + include: [ + { + model: Ticket, + as: "ticket", + include: ["contact"] + } + ] + }); + + if (!message) { + throw new AppError("No message found with this ID."); + } + + const { ticket } = message; + + const wbot = await GetTicketWbot(ticket); + + const msg = JSON.parse(message.dataJson); + + try { + await wbot.sendMessage(message.remoteJid, { + text: body, + edit: msg.key, + },{}); + + message.update({ body: body, isEdited: true}); + + return { ticket: message.ticket , message: message }; + } catch (err) { + console.log(err); + throw new AppError("ERR_EDITING_WAPP_MSG"); + } + +}; + +export default EditWhatsAppMessage; \ No newline at end of file diff --git a/backend/src/services/WbotServices/GetProfilePicUrl.ts b/backend/src/services/WbotServices/GetProfilePicUrl.ts new file mode 100644 index 0000000..4ae0fa9 --- /dev/null +++ b/backend/src/services/WbotServices/GetProfilePicUrl.ts @@ -0,0 +1,22 @@ +import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp"; +import { getWbot } from "../../libs/wbot"; + +const GetProfilePicUrl = async ( + number: string, + companyId: number +): Promise => { + const defaultWhatsapp = await GetDefaultWhatsApp(companyId); + + const wbot = getWbot(defaultWhatsapp.id); + + let profilePicUrl: string; + try { + profilePicUrl = await wbot.profilePictureUrl(`${number}@s.whatsapp.net`); + } catch (error) { + profilePicUrl = `${process.env.FRONTEND_URL}/nopicture.png`; + } + + return profilePicUrl; +}; + +export default GetProfilePicUrl; diff --git a/backend/src/services/WbotServices/ImportContactsService.ts b/backend/src/services/WbotServices/ImportContactsService.ts new file mode 100644 index 0000000..4e333d0 --- /dev/null +++ b/backend/src/services/WbotServices/ImportContactsService.ts @@ -0,0 +1,74 @@ +import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp"; +import { getWbot } from "../../libs/wbot"; +import Contact from "../../models/Contact"; +import { logger } from "../../utils/logger"; +import ShowBaileysService from "../BaileysServices/ShowBaileysService"; +import CreateContactService from "../ContactServices/CreateContactService"; +import AppError from "../../errors/AppError"; + +const ImportContactsService = async (companyId: number): Promise => { + const defaultWhatsapp = await GetDefaultWhatsApp(companyId); + const wbot = getWbot(defaultWhatsapp.id); + + const baileys = await ShowBaileysService(wbot.id); + + let phoneContactsList = null; + + try { + phoneContactsList = baileys.contacts && JSON.parse(baileys.contacts); + } catch (error) { + logger.warn( + { baileys }, + `Could not get whatsapp contacts from database. Err: ${error}` + ); + throw new AppError("Could not get whatsapp contacts from database.", 500); + } + + if (Array.isArray(phoneContactsList)) { + const processContacts = async contactsList => { + contactsList.forEach(async ({ id, name, notify }) => { + if (id === "status@broadcast" || id.includes("g.us")) return; + const number = id.replace(/\D/g, ""); + + const existingContact = await Contact.findOne({ + where: { number, companyId } + }); + + if (existingContact) { + // Atualiza o nome do contato existente + existingContact.name = name || notify || number; + await existingContact.save(); + } else { + // Criar um novo contato + try { + await CreateContactService({ + number, + name: name || notify || number, + companyId + }); + } catch (error) { + logger.error( + { name, number, companyId }, + `Could not save contact. Err: ${error}` + ); + } + } + }); + }; + + processContacts(phoneContactsList).then( + () => { + logger.debug( + `Contacts imported successfully from WhatsApp for company ID: ${companyId}` + ); + }, + error => { + logger.error( + `Error importing contacts from WhatsApp for company ID: ${companyId} - ${error.message}` + ); + } + ); + } +}; + +export default ImportContactsService; \ No newline at end of file diff --git a/backend/src/services/WbotServices/MarkDeleteWhatsAppMessage.ts b/backend/src/services/WbotServices/MarkDeleteWhatsAppMessage.ts new file mode 100644 index 0000000..afadef5 --- /dev/null +++ b/backend/src/services/WbotServices/MarkDeleteWhatsAppMessage.ts @@ -0,0 +1,64 @@ +import Message from "../../models/Message"; +import { getIO } from "../../libs/socket"; +import Ticket from "../../models/Ticket"; +import UpdateTicketService from "../TicketServices/UpdateTicketService"; + +const MarkDeleteWhatsAppMessage = async (from: any, timestamp?: any, msgId?: string, companyId?: number): Promise => { + + from = from.replace('@c.us', '').replace('@s.whatsapp.net', '') + + if (msgId) { + + const messages = await Message.findAll({ + where: { + id: msgId, + companyId + } + }); + + try { + const messageToUpdate = await Message.findByPk( + messages[0].id, { + include: [ + "contact", + { + model: Message, + as: "quotedMsg", + include: ["contact"] + } + ] + }); + + if (messageToUpdate) { + const ticket = await Ticket.findOne({ + where: { + id: messageToUpdate.ticketId, + companyId + } + }) + + + await messageToUpdate.update({ isDeleted: true }); + + + + await UpdateTicketService({ ticketData: { lastMessage: "🚫 _Mensagem Apagada_" }, ticketId: ticket.id, companyId }) + + const io = getIO(); + io.of(companyId.toString()) + // .to(messageToUpdate.ticketId.toString()) + .emit(`appMessage-${messageToUpdate}`, { + action: "update", + message: messageToUpdate + }); + } + } catch (err) { + console.log("Erro ao tentar marcar a mensagem com excluída") + } + + return timestamp; + }; + +} + +export default MarkDeleteWhatsAppMessage; diff --git a/backend/src/services/WbotServices/SendWhatsAppMedia.ts b/backend/src/services/WbotServices/SendWhatsAppMedia.ts new file mode 100644 index 0000000..996d12c --- /dev/null +++ b/backend/src/services/WbotServices/SendWhatsAppMedia.ts @@ -0,0 +1,280 @@ +import { WAMessage, AnyMessageContent } from "@whiskeysockets/baileys"; +import * as Sentry from "@sentry/node"; +import fs from "fs"; +import { exec } from "child_process"; +import path from "path"; +import ffmpeg from "fluent-ffmpeg"; +import AppError from "../../errors/AppError"; +import GetTicketWbot from "../../helpers/GetTicketWbot"; +import Ticket from "../../models/Ticket"; +import mime from "mime-types"; + +import ffmpegPath from "ffmpeg-static"; +import formatBody from "../../helpers/Mustache"; + +interface Request { + media: Express.Multer.File; + ticket: Ticket; + companyId?: number; + body?: string; + isForwarded?: boolean; +} + +ffmpeg.setFfmpegPath(ffmpegPath); + +const publicFolder = path.resolve(__dirname, "..", "..", "..", "public"); + +const processAudio = async (audio: string, companyId: string): Promise => { + const outputAudio = `${publicFolder}/company${companyId}/${new Date().getTime()}.ogg`; + return new Promise((resolve, reject) => { + exec( + `${ffmpegPath} -i ${audio} -vn -c:a libopus -b:a 128k ${outputAudio} -y`, + (error, _stdout, _stderr) => { + if (error) reject(error); + fs.unlinkSync(audio); + resolve(outputAudio); + } + ); + }); +}; + +const processAudioFile = async (audio: string, companyId: string): Promise => { + const outputAudio = `${publicFolder}/company${companyId}/${new Date().getTime()}.mp3`; + return new Promise((resolve, reject) => { + exec( + `${ffmpegPath} -i ${audio} -vn -ar 44100 -ac 2 -b:a 192k ${outputAudio}`, + (error, _stdout, _stderr) => { + if (error) reject(error); + fs.unlinkSync(audio); + resolve(outputAudio); + } + ); + }); +}; + + +/*export const getMessageOptions = async ( + fileName: string, + pathMedia: string, + companyId?: string, + body?: string +): Promise => { + const mimeType = mime.lookup(pathMedia); + const typeMessage = mimeType.split("/")[0]; + + try { + if (!mimeType) { + throw new Error("Invalid mimetype"); + } + + // Ajuste: Adiciona o subdiretório company${companyId} ao caminho, se companyId existir + const correctedPath = companyId + ? path.join(publicFolder, `company${companyId}`, fileName) + : pathMedia; + + let options: AnyMessageContent; + + if (typeMessage === "video") { + options = { + video: fs.readFileSync(pathMedia), + caption: body ? body : '', + fileName: fileName + // gifPlayback: true + }; + } else if (typeMessage === "audio") { + const typeAudio = true; //fileName.includes("audio-record-site"); + const convert = await processAudio(pathMedia, companyId); + if (typeAudio) { + options = { + audio: fs.readFileSync(convert), + mimetype: "audio/ogg; codecs=opus", + ptt: true, // Certifique-se de que PTT está definido corretamente + }; + } else { + options = { + audio: fs.readFileSync(convert), + mimetype: typeAudio ? "audio/mp4" : mimeType, + ptt: true + }; + } + } else if (typeMessage === "document") { + options = { + document: fs.readFileSync(pathMedia), + caption: body ? body : null, + fileName: fileName, + mimetype: mimeType + }; + } else if (typeMessage === "application") { + options = { + document: fs.readFileSync(pathMedia), + caption: body ? body : null, + fileName: fileName, + mimetype: mimeType + }; + } else { + options = { + image: fs.readFileSync(pathMedia), + caption: body ? body : null + }; + } + + return options; + } catch (e) { + Sentry.captureException(e); + console.log(e); + return null; + } +};*/ + + +export const getMessageOptions = async ( + fileName: string, + pathMedia: string, + companyId?: string, + body?: string +): Promise => { + const mimeType = mime.lookup(pathMedia); + const typeMessage = mimeType.split("/")[0]; + + try { + if (!mimeType) { + throw new Error("Invalid mimetype"); + } + + // Ajuste: Adiciona o subdiretório company${companyId} ao caminho, se companyId existir + const correctedPath = companyId + ? path.join(publicFolder, `company${companyId}`, fileName) + : pathMedia; + + let options: AnyMessageContent; + + if (typeMessage === "video") { + options = { + video: fs.readFileSync(correctedPath), + caption: body ? body : '', + fileName: fileName + }; + } else if (typeMessage === "audio") { + const typeAudio = true; // fileName.includes("audio-record-site"); + const convert = await processAudio(correctedPath, companyId); + if (typeAudio) { + options = { + audio: fs.readFileSync(convert), + mimetype: "audio/ogg; codecs=opus", + ptt: true + }; + } else { + options = { + audio: fs.readFileSync(convert), + mimetype: typeAudio ? "audio/mp4" : mimeType, + ptt: true + }; + } + } else if (typeMessage === "document") { + options = { + document: fs.readFileSync(correctedPath), + caption: body ? body : null, + fileName: fileName, + mimetype: mimeType + }; + } else if (typeMessage === "application") { + options = { + document: fs.readFileSync(correctedPath), + caption: body ? body : null, + fileName: fileName, + mimetype: mimeType + }; + } else { + options = { + image: fs.readFileSync(correctedPath), + caption: body ? body : null + }; + } + + return options; + } catch (e) { + Sentry.captureException(e); + console.log(e); + return null; + } +}; + +const SendWhatsAppMedia = async ({ + media, + ticket, + body, + isForwarded = false +}: Request): Promise => { + try { + const wbot = await GetTicketWbot(ticket); + const companyId = ticket.companyId.toString(); + + const pathMedia = media.path; + const typeMessage = media.mimetype.split("/")[0]; + let options: AnyMessageContent; + const bodyMessage = formatBody(body, ticket.contact) + + if (typeMessage === "video") { + options = { + video: fs.readFileSync(pathMedia), + caption: bodyMessage, + fileName: media.originalname.replace('/', '-') + // gifPlayback: true + }; + } else if (typeMessage === "audio") { + const typeAudio = media.originalname.includes("audio-record-site"); + if (typeAudio) { + const convert = await processAudio(media.path, companyId); + options = { + audio: fs.readFileSync(convert), + mimetype: typeAudio ? "audio/mp4" : media.mimetype, + ptt: true + }; + } else { + const convert = await processAudioFile(media.path, companyId); + options = { + audio: fs.readFileSync(convert), + mimetype: typeAudio ? "audio/mp4" : media.mimetype + }; + } + } else if (typeMessage === "document" || typeMessage === "text") { + options = { + document: fs.readFileSync(pathMedia), + caption: bodyMessage, + fileName: media.originalname.replace('/', '-'), + mimetype: media.mimetype + }; + } else if (typeMessage === "application") { + options = { + document: fs.readFileSync(pathMedia), + caption: bodyMessage, + fileName: media.originalname.replace('/', '-'), + mimetype: media.mimetype + }; + } else { + options = { + image: fs.readFileSync(pathMedia), + caption: bodyMessage + }; + } + + const sentMessage = await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + { + ...options + } + ); + + await ticket.update({ lastMessage: bodyMessage }); + + return sentMessage; + } catch (err) { + Sentry.captureException(err); + console.log(err); + throw new AppError("ERR_SENDING_WAPP_MSG"); + } +}; + +export default SendWhatsAppMedia; + + diff --git a/backend/src/services/WbotServices/SendWhatsAppMessage.ts b/backend/src/services/WbotServices/SendWhatsAppMessage.ts new file mode 100644 index 0000000..b259b60 --- /dev/null +++ b/backend/src/services/WbotServices/SendWhatsAppMessage.ts @@ -0,0 +1,73 @@ +import * as Sentry from "@sentry/node"; +import { WAMessage } from "@whiskeysockets/baileys"; +import AppError from "../../errors/AppError"; +import GetTicketWbot from "../../helpers/GetTicketWbot"; +import Message from "../../models/Message"; +import Ticket from "../../models/Ticket"; + +import formatBody from "../../helpers/Mustache"; +import { map_msg } from "../../utils/global"; + +interface Request { + body: string; + ticket: Ticket; + quotedMsg?: Message; + isForwarded?: boolean; +} + +const SendWhatsAppMessage = async ({ + body, + ticket, + quotedMsg, + isForwarded = false +}: Request): Promise => { + let options = {}; + const wbot = await GetTicketWbot(ticket); + const number = `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net" + }`; + console.log("number", number); + if (quotedMsg) { + const chatMessages = await Message.findOne({ + where: { + id: quotedMsg.id + } + }); + + if (chatMessages) { + const msgFound = JSON.parse(chatMessages.dataJson); + + options = { + quoted: { + key: msgFound.key, + message: { + extendedTextMessage: msgFound.message.extendedTextMessage + } + } + }; + } + + } + + try { + console.log('body:::::::::::::::::::::::::::', body) + map_msg.set(ticket.contact.number, { lastSystemMsg: body }) + console.log('lastSystemMsg:::::::::::::::::::::::::::', ticket.contact.number) + const sentMessage = await wbot.sendMessage(number, { + text: formatBody(body, ticket.contact), + contextInfo: { forwardingScore: isForwarded ? 2 : 0, isForwarded: isForwarded ? true : false } + }, + { + ...options + } + ); + await ticket.update({ lastMessage: formatBody(body, ticket.contact) }); + console.log("Message sent", sentMessage); + return sentMessage; + } catch (err) { + Sentry.captureException(err); + console.log(err); + throw new AppError("ERR_SENDING_WAPP_MSG"); + } +}; + +export default SendWhatsAppMessage; diff --git a/backend/src/services/WbotServices/SendWhatsAppReaction.ts b/backend/src/services/WbotServices/SendWhatsAppReaction.ts new file mode 100644 index 0000000..5069be1 --- /dev/null +++ b/backend/src/services/WbotServices/SendWhatsAppReaction.ts @@ -0,0 +1,64 @@ +import { WAMessage } from "@whiskeysockets/baileys"; +import WALegacySocket from "@whiskeysockets/baileys"; +import * as Sentry from "@sentry/node"; +import AppError from "../../errors/AppError"; +import GetTicketWbot from "../../helpers/GetTicketWbot"; +import Message from "../../models/Message"; +import Ticket from "../../models/Ticket"; +import SendWhatsAppMessage from "./SendWhatsAppMessage"; +import formatBody from "../../helpers/Mustache"; +import {getBodyMessage} from "./wbotMessageListener"; +import CreateMessageService from "../MessageServices/CreateMessageService"; + +interface ReactionRequest { + messageId: string; + ticket: Ticket; + reactionType: string; // Exemplo: 'like', 'heart', etc. +} + +const SendWhatsAppReaction = async ({ + messageId, + ticket, + reactionType +}: ReactionRequest): Promise => { + const wbot = await GetTicketWbot(ticket); + + const number = `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`; + + try { + const messageToReact = await Message.findOne({ + where: { + id: messageId + } + }); + + if (!messageToReact) { + throw new AppError("Message not found"); + } + + if (!reactionType) { + throw new AppError("ReactionType not found"); + } + + const msgFound = JSON.parse(messageToReact.dataJson); + + console.log(reactionType); + + const msg = await wbot.sendMessage(number, { + react: { + text: reactionType, // O tipo de reação + key: msgFound.key // A chave da mensagem original a qual a reação se refere + } + + }); + + + return msg; + } catch (err) { + Sentry.captureException(err); + console.log(err); + throw new AppError("ERR_SENDING_WAPP_REACTION"); + } +}; + +export default SendWhatsAppReaction; diff --git a/backend/src/services/WbotServices/StartAllWhatsAppsSessions.ts b/backend/src/services/WbotServices/StartAllWhatsAppsSessions.ts new file mode 100644 index 0000000..2a0b7d2 --- /dev/null +++ b/backend/src/services/WbotServices/StartAllWhatsAppsSessions.ts @@ -0,0 +1,23 @@ +import { setChannelWebhook } from "../../helpers/setChannelHubWebhook"; +import ListWhatsAppsService from "../WhatsappService/ListWhatsAppsService"; +import { StartWhatsAppSession } from "./StartWhatsAppSession"; +import * as Sentry from "@sentry/node"; + +export const StartAllWhatsAppsSessions = async ( + companyId: number +): Promise => { + try { + const whatsapps = await ListWhatsAppsService({ companyId }); + if (whatsapps.length > 0) { + whatsapps.forEach(whatsapp => { + if(whatsapp.type !== null) { + setChannelWebhook(whatsapp, whatsapp.id.toString()); + } else { + StartWhatsAppSession(whatsapp, companyId); + } + }); + } + } catch (e) { + Sentry.captureException(e); + } +}; diff --git a/backend/src/services/WbotServices/StartWhatsAppSession.ts b/backend/src/services/WbotServices/StartWhatsAppSession.ts new file mode 100644 index 0000000..7f8dc52 --- /dev/null +++ b/backend/src/services/WbotServices/StartWhatsAppSession.ts @@ -0,0 +1,31 @@ +import { initWASocket } from "../../libs/wbot"; +import Whatsapp from "../../models/Whatsapp"; +import { wbotMessageListener } from "./wbotMessageListener"; +import { getIO } from "../../libs/socket"; +import wbotMonitor from "./wbotMonitor"; +import { logger } from "../../utils/logger"; +import * as Sentry from "@sentry/node"; + +export const StartWhatsAppSession = async ( + whatsapp: Whatsapp, + companyId: number +): Promise => { + await whatsapp.update({ status: "OPENING" }); + + const io = getIO(); + io.emit(`company-${companyId}-whatsappSession`, { + action: "update", + session: whatsapp + }); + + + try { + const wbot = await initWASocket(whatsapp); + + wbotMessageListener(wbot, companyId); + await wbotMonitor(wbot, whatsapp, companyId); + } catch (err) { + Sentry.captureException(err); + logger.error(err); + } +}; diff --git a/backend/src/services/WbotServices/providers.ts b/backend/src/services/WbotServices/providers.ts new file mode 100644 index 0000000..b8ee4c0 --- /dev/null +++ b/backend/src/services/WbotServices/providers.ts @@ -0,0 +1,1527 @@ +import { proto, WASocket } from "@whiskeysockets/baileys"; +import Contact from "../../models/Contact"; +import Setting from "../../models/Setting"; +import Ticket from "../../models/Ticket"; +import { getBodyMessage, isNumeric, sleep, validaCpfCnpj, sendMessageImage, sendMessageLink, makeid } from "./wbotMessageListener"; +import formatBody from "../../helpers/Mustache"; + +import puppeteer from "puppeteer"; + +import axios from 'axios'; +import UpdateTicketService from "../TicketServices/UpdateTicketService"; +import fs from 'fs'; + +export const provider = async (ticket: Ticket, msg: proto.IWebMessageInfo, companyId: number, contact: Contact, wbot: WASocket) => { + const filaescolhida = ticket.queue?.name + if (filaescolhida === "2ª Via de Boleto" || filaescolhida === "2 Via de Boleto") { + let cpfcnpj + cpfcnpj = getBodyMessage(msg); + cpfcnpj = cpfcnpj.replace(/\./g, ''); + cpfcnpj = cpfcnpj.replace('-', '') + cpfcnpj = cpfcnpj.replace('/', '') + cpfcnpj = cpfcnpj.replace(' ', '') + cpfcnpj = cpfcnpj.replace(',', '') + + const asaastoken = await Setting.findOne({ + where: { + key: "asaas", + companyId + } + }); + const ixcapikey = await Setting.findOne({ + where: { + key: "tokenixc", + companyId + } + }); + const urlixcdb = await Setting.findOne({ + where: { + key: "ipixc", + companyId + } + }); + const ipmkauth = await Setting.findOne({ + where: { + key: "ipmkauth", + companyId + } + }); + const clientidmkauth = await Setting.findOne({ + where: { + key: "clientidmkauth", + companyId + } + }); + const clientesecretmkauth = await Setting.findOne({ + where: { + key: "clientsecretmkauth", + companyId + } + }); + + let urlmkauth = ipmkauth.value + if (urlmkauth.substr(-1) === '/') { + urlmkauth = urlmkauth.slice(0, -1); + } + + //VARS + let url = `${urlmkauth}/api/`; + const Client_Id = clientidmkauth.value + const Client_Secret = clientesecretmkauth.value + const ixckeybase64 = btoa(ixcapikey.value); + const urlixc = urlixcdb.value + const asaastk = asaastoken.value + + const cnpj_cpf = getBodyMessage(msg); + let numberCPFCNPJ = cpfcnpj; + + if (urlmkauth != "" && Client_Id != "" && Client_Secret != "") { + if (isNumeric(numberCPFCNPJ) === true) { + if (cpfcnpj.length > 2) { + const isCPFCNPJ = validaCpfCnpj(numberCPFCNPJ) + if (isCPFCNPJ) { + const textMessage = { + text: formatBody(`Aguarde! Estamos consultando na base de dados!`, contact), + }; + try { + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, textMessage); + } catch (error) { + + } + + + axios({ + rejectUnauthorized: true, + method: 'get', + url, + auth: { + username: Client_Id, + password: Client_Secret + } + } as any) + .then(function (response) { + const jtw = response.data + var config = { + method: 'GET', + url: `${urlmkauth}/api/cliente/show/${numberCPFCNPJ}`, + headers: { + Authorization: `Bearer ${jtw}` + } + }; + axios.request(config as any) + .then(async function (response) { + if (response.data == 'NULL') { + const textMessage = { + text: formatBody(`Cadastro não localizado! *CPF/CNPJ* incorreto ou inválido. Tenta novamente!`, contact), + }; + try { + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, textMessage); + } catch (error) { + console.log('Não consegui enviar a mensagem!') + } + } else { + let nome + let cpf_cnpj + let qrcode + let valor + let bloqueado + let linhadig + let uuid_cliente + let referencia + let status + let datavenc + let descricao + let titulo + let statusCorrigido + let valorCorrigido + + nome = response.data.dados_cliente.titulos.nome + cpf_cnpj = response.data.dados_cliente.titulos.cpf_cnpj + valor = response.data.dados_cliente.titulos.valor + bloqueado = response.data.dados_cliente.titulos.bloqueado + uuid_cliente = response.data.dados_cliente.titulos.uuid_cliente + qrcode = response.data.dados_cliente.titulos.qrcode + linhadig = response.data.dados_cliente.titulos.linhadig + referencia = response.data.dados_cliente.titulos.referencia + status = response.data.dados_cliente.titulos.status + datavenc = response.data.dados_cliente.titulos.datavenc + descricao = response.data.dados_cliente.titulos.descricao + titulo = response.data.dados_cliente.titulos.titulo + statusCorrigido = status[0].toUpperCase() + status.substr(1); + valorCorrigido = valor.replace(".", ","); + + var curdate = new Date(datavenc) + const mesCorreto = curdate.getMonth() + 1 + const ano = ('0' + curdate.getFullYear()).slice(-4) + const mes = ('0' + mesCorreto).slice(-2) + const dia = ('0' + curdate.getDate()).slice(-2) + const anoMesDia = `${dia}/${mes}/${ano}` + + try { + const textMessage = { text: formatBody(`Localizei seu Cadastro! *${nome}* só mais um instante por favor!`, contact) }; + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, textMessage); + const bodyBoleto = { text: formatBody(`Segue a segunda-via da sua Fatura!\n\n*Nome:* ${nome}\n*Valor:* R$ ${valorCorrigido}\n*Data Vencimento:* ${anoMesDia}\n*Link:* ${urlmkauth}/boleto/21boleto.php?titulo=${titulo}\n\nVou mandar o *código de barras* na próxima mensagem para ficar mais fácil para você copiar!`, contact) }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyBoleto); + const bodyLinha = { text: formatBody(`${linhadig}`, contact) }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyLinha); + if (qrcode !== null) { + const bodyPdf = { text: formatBody(`Este é o *PIX COPIA E COLA*`, contact) }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyPdf); + const bodyqrcode = { text: formatBody(`${qrcode}`, contact) }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyqrcode); + let linkBoleto = `https://chart.googleapis.com/chart?cht=qr&chs=500x500&chld=L|0&chl=${qrcode}` + await sleep(2000) + await sendMessageImage(wbot, contact, ticket, linkBoleto, "") + } + const bodyPdf = { text: formatBody(`Agora vou te enviar o boleto em *PDF* caso você precise.`, contact) }; + await sleep(2000) + const bodyPdfQr = { text: formatBody(`${bodyPdf}`, contact) }; + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyPdfQr); + await sleep(2000) + + //GERA O PDF + const nomePDF = `Boleto-${nome}-${dia}-${mes}-${ano}.pdf`; + (async () => { + const browser = await puppeteer.launch({ args: ['--no-sandbox'] }); + const page = await browser.newPage(); + const website_url = `${urlmkauth}/boleto/21boleto.php?titulo=${titulo}`; + await page.goto(website_url, { waitUntil: 'networkidle0' }); + await page.emulateMediaType('screen'); + // Downlaod the PDF + const pdf = await page.pdf({ + path: nomePDF, + printBackground: true, + format: 'A4', + }); + + await browser.close(); + await sendMessageLink(wbot, contact, ticket, nomePDF, nomePDF); + }); + + + if (bloqueado === 'sim') { + const bodyBloqueio = { text: formatBody(`${nome} vi tambem que a sua conexão esta bloqueada! Vou desbloquear para você por *48 horas*.`, contact) }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyBloqueio); + const bodyqrcode = { text: formatBody(`Estou liberando seu acesso. Por favor aguarde!`, contact) }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyqrcode); + var optionsdesbloq = { + method: 'GET', + url: `${urlmkauth}/api/cliente/desbloqueio/${uuid_cliente}`, + headers: { + Authorization: `Bearer ${jtw}` + } + }; + axios.request(optionsdesbloq as any).then(async function (response) { + const bodyLiberado = { text: formatBody(`Pronto liberei! Vou precisar que você *retire* seu equipamento da tomada.\n\n*OBS: Somente retire da tomada.* \nAguarde 1 minuto e ligue novamente!`, contact) }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyLiberado); + const bodyqrcode = { text: formatBody(`Veja se seu acesso voltou! Caso nao tenha voltado retorne o contato e fale com um atendente!`, contact) }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyqrcode); + }).catch(async function (error) { + const bodyfinaliza = { text: formatBody(`Opss! Algo de errado aconteceu! Digite *#* para voltar ao menu anterior e fale com um atendente!`, contact) }; + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + }); + } + + + const bodyfinaliza = { text: formatBody(`Estamos finalizando esta conversa! Caso precise entre em contato conosco!`, contact) }; + await sleep(12000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + + await sleep(2000) + fs.unlink(nomePDF, function (err) { + if (err) throw err; + console.log(err); + }) + + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + + } catch (error) { + console.log('11 Não consegui enviar a mensagem!') + } + } + }) + .catch(async function (error) { + try { + const bodyBoleto = { text: formatBody(`Não consegui encontrar seu cadastro.\n\nPor favor tente novamente!\nOu digite *#* para voltar ao *Menu Anterior*`, contact) }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyBoleto); + } catch (error) { + console.log('111 Não consegui enviar a mensagem!') + } + + }); + }) + .catch(async function (error) { + const bodyfinaliza = { text: formatBody(`Opss! Algo de errado aconteceu! Digite *#* para voltar ao menu anterior e fale com um atendente!`, contact) }; + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + }); + } else { + const body = { text: formatBody(`Este CPF/CNPJ não é válido!\n\nPor favor tente novamente!\nOu digite *#* para voltar ao *Menu Anterior*`, contact) }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + } + } + } + } + + if (asaastoken.value !== "") { + if (isNumeric(numberCPFCNPJ) === true) { + if (cpfcnpj.length > 2) { + const isCPFCNPJ = validaCpfCnpj(numberCPFCNPJ) + if (isCPFCNPJ) { + const body = { + text: formatBody(`Aguarde! Estamos consultando na base de dados!`, contact), + }; + try { + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + } catch (error) { + } + var optionsc = { + method: 'GET', + url: 'https://www.asaas.com/api/v3/customers', + params: { cpfCnpj: numberCPFCNPJ }, + headers: { + 'Content-Type': 'application/json', + access_token: asaastk + } + }; + + axios.request(optionsc as any).then(async function (response) { + let nome; + let id_cliente; + let totalCount; + + nome = response?.data?.data[0]?.name; + id_cliente = response?.data?.data[0]?.id; + totalCount = response?.data?.totalCount; + + if (totalCount === 0) { + const body = { + text: formatBody(`Cadastro não localizado! *CPF/CNPJ* incorreto ou inválido. Tenta novamente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + } else { + + const body = { + text: formatBody(`Localizei seu Cadastro! \n*${nome}* só mais um instante por favor!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + var optionsListpaymentOVERDUE = { + method: 'GET', + url: 'https://www.asaas.com/api/v3/payments', + params: { customer: id_cliente, status: 'OVERDUE' }, + headers: { + 'Content-Type': 'application/json', + access_token: asaastk + } + }; + + axios.request(optionsListpaymentOVERDUE as any).then(async function (response) { + let totalCount_overdue; + totalCount_overdue = response?.data?.totalCount; + + if (totalCount_overdue === 0) { + const body = { + text: formatBody(`Você não tem nenhuma fatura vencidada! \nVou te enviar a proxima fatura. Por favor aguarde!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + var optionsPENDING = { + method: 'GET', + url: 'https://www.asaas.com/api/v3/payments', + params: { customer: id_cliente, status: 'PENDING' }, + headers: { + 'Content-Type': 'application/json', + access_token: asaastk + } + }; + + axios.request(optionsPENDING as any).then(async function (response) { + function sortfunction(a, b) { + return a.dueDate.localeCompare(b.dueDate); + } + const ordenado = response?.data?.data.sort(sortfunction); + let id_payment_pending; + let value_pending; + let description_pending; + let invoiceUrl_pending; + let dueDate_pending; + let invoiceNumber_pending; + let totalCount_pending; + let value_pending_corrigida; + let dueDate_pending_corrigida; + + id_payment_pending = ordenado[0]?.id; + value_pending = ordenado[0]?.value; + description_pending = ordenado[0]?.description; + invoiceUrl_pending = ordenado[0]?.invoiceUrl; + dueDate_pending = ordenado[0]?.dueDate; + invoiceNumber_pending = ordenado[0]?.invoiceNumber; + totalCount_pending = response?.data?.totalCount; + + dueDate_pending_corrigida = dueDate_pending?.split('-')?.reverse()?.join('/'); + value_pending_corrigida = value_pending.toLocaleString('pt-br', { style: 'currency', currency: 'BRL' }); + + const bodyBoleto = { + text: formatBody(`Segue a segunda-via da sua Fatura!\n\n*Fatura:* ${invoiceNumber_pending}\n*Nome:* ${nome}\n*Valor:* R$ ${value_pending_corrigida}\n*Data Vencimento:* ${dueDate_pending_corrigida}\n*Descrição:*\n${description_pending}\n*Link:* ${invoiceUrl_pending}`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyBoleto); + //GET DADOS PIX + var optionsGetPIX = { + method: 'GET', + url: `https://www.asaas.com/api/v3/payments/${id_payment_pending}/pixQrCode`, + headers: { + 'Content-Type': 'application/json', + access_token: asaastk + } + }; + + axios.request(optionsGetPIX as any).then(async function (response) { + let success; + let payload; + + success = response?.data?.success; + payload = response?.data?.payload; + + if (success === true) { + const bodyPixCP = { + text: formatBody(`Este é o *PIX Copia e Cola*`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyPixCP); + const bodyPix = { + text: formatBody(`${payload}`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyPix); + let linkBoleto = `https://chart.googleapis.com/chart?cht=qr&chs=500x500&chld=L|0&chl=${payload}` + await sleep(2000) + await sendMessageImage(wbot, contact, ticket, linkBoleto, '') + var optionsBoletopend = { + method: 'GET', + url: `https://www.asaas.com/api/v3/payments/${id_payment_pending}/identificationField`, + headers: { + 'Content-Type': 'application/json', + access_token: asaastk + } + }; + + axios.request(optionsBoletopend as any).then(async function (response) { + let codigo_barras + codigo_barras = response.data.identificationField; + const bodycodigoBarras = { + text: formatBody(`${codigo_barras}`, contact), + }; + if (response.data?.errors?.code !== 'invalid_action') { + const bodycodigo = { + text: formatBody(`Este é o *Código de Barras*!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodycodigo); + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodycodigoBarras); + const bodyfinaliza = { + text: formatBody(`Estamos finalizando esta conversa! Caso precise entre em contato conosco!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + await sleep(2000) + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + } else { + const bodyfinaliza = { + text: formatBody(`Estamos finalizando esta conversa! Caso precise entre em contato conosco!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + } + + }).catch(async function (error) { + const bodyfinaliza = { + text: formatBody(`Estamos finalizando esta conversa! Caso precise entre em contato conosco!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + }); + } + + }).catch(async function (error) { + const body = { + text: formatBody(`*Opss!!!!*\nOcorreu um erro! Digite *#* e fale com um *Atendente*!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + }); + + }).catch(async function (error) { + const body = { + text: formatBody(`*Opss!!!!*\nOcorreu um erro! Digite *#* e fale com um *Atendente*!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + }); + } else { + let id_payment_overdue; + let value_overdue; + let description_overdue; + let invoiceUrl_overdue; + let dueDate_overdue; + let invoiceNumber_overdue; + + let value_overdue_corrigida; + let dueDate_overdue_corrigida; + + id_payment_overdue = response?.data?.data[0]?.id; + value_overdue = response?.data?.data[0]?.value; + description_overdue = response?.data?.data[0]?.description; + invoiceUrl_overdue = response?.data?.data[0]?.invoiceUrl; + dueDate_overdue = response?.data?.data[0]?.dueDate; + invoiceNumber_overdue = response?.data?.data[0]?.invoiceNumber; + + + dueDate_overdue_corrigida = dueDate_overdue?.split('-')?.reverse()?.join('/'); + value_overdue_corrigida = value_overdue.toLocaleString('pt-br', { style: 'currency', currency: 'BRL' }); + const body = { + text: formatBody(`Você tem *${totalCount_overdue}* fatura(s) vencidada(s)! \nVou te enviar. Por favor aguarde!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + const bodyBoleto = { + text: formatBody(`Segue a segunda-via da sua Fatura!\n\n*Fatura:* ${invoiceNumber_overdue}\n*Nome:* ${nome}\n*Valor:* R$ ${value_overdue_corrigida}\n*Data Vencimento:* ${dueDate_overdue_corrigida}\n*Descrição:*\n${description_overdue}\n*Link:* ${invoiceUrl_overdue}`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyBoleto); + //GET DADOS PIX + var optionsGetPIX = { + method: 'GET', + url: `https://www.asaas.com/api/v3/payments/${id_payment_overdue}/pixQrCode`, + headers: { + 'Content-Type': 'application/json', + access_token: asaastk + } + }; + + axios.request(optionsGetPIX as any).then(async function (response) { + let success; + let payload; + + success = response?.data?.success; + payload = response?.data?.payload; + if (success === true) { + + const bodyPixCP = { + text: formatBody(`Este é o *PIX Copia e Cola*`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyPixCP); + const bodyPix = { + text: formatBody(`${payload}`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyPix); + let linkBoleto = `https://chart.googleapis.com/chart?cht=qr&chs=500x500&chld=L|0&chl=${payload}` + await sleep(2000) + await sendMessageImage(wbot, contact, ticket, linkBoleto, '') + var optionsBoleto = { + method: 'GET', + url: `https://www.asaas.com/api/v3/payments/${id_payment_overdue}/identificationField`, + headers: { + 'Content-Type': 'application/json', + access_token: asaastk + } + }; + + axios.request(optionsBoleto as any).then(async function (response) { + + let codigo_barras + codigo_barras = response.data.identificationField; + const bodycodigoBarras = { + text: formatBody(`${codigo_barras}`, contact), + }; + if (response.data?.errors?.code !== 'invalid_action') { + const bodycodigo = { + text: formatBody(`Este é o *Código de Barras*!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodycodigo); + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodycodigoBarras); + const bodyfinaliza = { + text: formatBody(`Estamos finalizando esta conversa! Caso precise entre em contato conosco!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + } else { + const bodyfinaliza = { + text: formatBody(`Estamos finalizando esta conversa! Caso precise entre em contato conosco!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + } + + }).catch(function (error) { + //console.error(error); + }); + + } + }).catch(function (error) { + + }); + + } + + }).catch(async function (error) { + const body = { + text: formatBody(`*Opss!!!!*\nOcorreu um erro! Digite *#* e fale com um *Atendente*!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + }); + } + }).catch(async function (error) { + const body = { + text: formatBody(`*Opss!!!!*\nOcorreu um erro! Digite *#* e fale com um *Atendente*!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + }); + } + } + } + } + + if (ixcapikey.value != "" && urlixcdb.value != "") { + if (isNumeric(numberCPFCNPJ) === true) { + if (cpfcnpj.length > 2) { + const isCPFCNPJ = validaCpfCnpj(numberCPFCNPJ) + if (isCPFCNPJ) { + if (numberCPFCNPJ.length <= 11) { + numberCPFCNPJ = numberCPFCNPJ.replace(/(\d{3})(\d)/, "$1.$2") + numberCPFCNPJ = numberCPFCNPJ.replace(/(\d{3})(\d)/, "$1.$2") + numberCPFCNPJ = numberCPFCNPJ.replace(/(\d{3})(\d{1,2})$/, "$1-$2") + } else { + numberCPFCNPJ = numberCPFCNPJ.replace(/^(\d{2})(\d)/, "$1.$2") + numberCPFCNPJ = numberCPFCNPJ.replace(/^(\d{2})\.(\d{3})(\d)/, "$1.$2.$3") + numberCPFCNPJ = numberCPFCNPJ.replace(/\.(\d{3})(\d)/, ".$1/$2") + numberCPFCNPJ = numberCPFCNPJ.replace(/(\d{4})(\d)/, "$1-$2") + } + //const token = await CheckSettingsHelper("OBTEM O TOKEN DO BANCO (dei insert na tabela settings)") + const body = { + text: formatBody(`Aguarde! Estamos consultando na base de dados!`, contact), + }; + try { + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + } catch (error) { + } + var options = { + method: 'GET', + url: `${urlixc}/webservice/v1/cliente`, + headers: { + ixcsoft: 'listar', + Authorization: `Basic ${ixckeybase64}` + }, + data: { + qtype: 'cliente.cnpj_cpf', + query: numberCPFCNPJ, + oper: '=', + page: '1', + rp: '1', + sortname: 'cliente.cnpj_cpf', + sortorder: 'asc' + } + }; + + axios.request(options as any).then(async function (response) { + if (response.data.type === 'error') { + console.log("Error response", response.data.message); + const body = { + text: formatBody(`*Opss!!!!*\nOcorreu um erro! Digite *#* e fale com um *Atendente*!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + } if (response.data.total === 0) { + const body = { + text: formatBody(`Cadastro não localizado! *CPF/CNPJ* incorreto ou inválido. Tenta novamente!`, contact), + }; + try { + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + } catch (error) { + } + } else { + + let nome; + let id; + let type; + + nome = response.data?.registros[0]?.razao + id = response.data?.registros[0]?.id + type = response.data?.type + + + const body = { + text: formatBody(`Localizei seu Cadastro! \n*${nome}* só mais um instante por favor!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + var boleto = { + method: 'GET', + url: `${urlixc}/webservice/v1/fn_areceber`, + headers: { + ixcsoft: 'listar', + Authorization: `Basic ${ixckeybase64}` + }, + data: { + qtype: 'fn_areceber.id_cliente', + query: id, + oper: '=', + page: '1', + rp: '1', + sortname: 'fn_areceber.data_vencimento', + sortorder: 'asc', + grid_param: '[{"TB":"fn_areceber.status", "OP" : "=", "P" : "A"}]' + } + }; + axios.request(boleto as any).then(async function (response) { + + + + let gateway_link; + let valor; + let datavenc; + let datavencCorrigida; + let valorCorrigido; + let linha_digitavel; + let impresso; + let idboleto; + + idboleto = response.data?.registros[0]?.id + gateway_link = response.data?.registros[0]?.gateway_link + valor = response.data?.registros[0]?.valor + datavenc = response.data?.registros[0]?.data_vencimento + linha_digitavel = response.data?.registros[0]?.linha_digitavel + impresso = response.data?.registros[0]?.impresso + valorCorrigido = valor.replace(".", ","); + datavencCorrigida = datavenc.split('-').reverse().join('/') + + + //INFORMAÇÕES BOLETO + const bodyBoleto = { + text: formatBody(`Segue a segunda-via da sua Fatura!\n\n*Fatura:* ${idboleto}\n*Nome:* ${nome}\n*Valor:* R$ ${valorCorrigido}\n*Data Vencimento:* ${datavencCorrigida}\n\nVou mandar o *código de barras* na próxima mensagem para ficar mais fácil para você copiar!`, contact), + }; + //await sleep(2000) + //await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyBoleto); + //LINHA DIGITAVEL + if (impresso !== "S") { + //IMPRIME BOLETO PARA GERAR CODIGO BARRAS + var boletopdf = { + method: 'GET', + url: `${urlixc}/webservice/v1/get_boleto`, + headers: { + ixcsoft: 'listar', + Authorization: `Basic ${ixckeybase64}` + }, + data: { + boletos: idboleto, + juro: 'N', + multa: 'N', + atualiza_boleto: 'N', + tipo_boleto: 'arquivo', + base64: 'S' + } + }; + + axios.request(boletopdf as any).then(function (response) { + }).catch(function (error) { + console.error(error); + }); + } + + //SE TIVER PIX ENVIA O PIX + var optionsPix = { + method: 'GET', + url: `${urlixc}/webservice/v1/get_pix`, + headers: { + ixcsoft: 'listar', + Authorization: `Basic ${ixckeybase64}` + }, + data: { id_areceber: idboleto } + }; + + axios.request(optionsPix as any).then(async function (response) { + let tipo; + let pix; + + tipo = response.data?.type; + pix = response.data?.pix?.qrCode?.qrcode; + if (tipo === 'success') { + const bodyBoletoPix = { + text: formatBody(`Segue a segunda-via da sua Fatura!\n\n*Fatura:* ${idboleto}\n*Nome:* ${nome}\n*Valor:* R$ ${valorCorrigido}\n*Data Vencimento:* ${datavencCorrigida}\n\nVou te enviar o *Código de Barras* e o *PIX* basta clicar em qual você quer utlizar que já vai copiar! Depois basta realizar o pagamento no seu banco`, contact), + }; + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyBoletoPix); + const body_linhadigitavel = { + text: formatBody("Este é o *Código de Barras*", contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body_linhadigitavel); + await sleep(2000) + const body_linha_digitavel = { + text: formatBody(`${linha_digitavel}`, contact), + }; + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body_linha_digitavel); + const body_pix = { + text: formatBody("Este é o *PIX Copia e Cola*", contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body_pix); + await sleep(2000) + const body_pix_dig = { + text: formatBody(`${pix}`, contact), + }; + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body_pix_dig); + const body_pixqr = { + text: formatBody("QR CODE do *PIX*", contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body_pixqr); + let linkBoleto = `https://chart.googleapis.com/chart?cht=qr&chs=500x500&chld=L|0&chl=${pix}` + await sleep(2000) + await sendMessageImage(wbot, contact, ticket, linkBoleto, '') + ///VE SE ESTA BLOQUEADO PARA LIBERAR! + var optionscontrato = { + method: 'POST', + url: `${urlixc}/webservice/v1/cliente_contrato`, + headers: { + ixcsoft: 'listar', + Authorization: `Basic ${ixckeybase64}` + }, + data: { + qtype: 'cliente_contrato.id_cliente', + query: id, + oper: '=', + page: '1', + rp: '1', + sortname: 'cliente_contrato.id', + sortorder: 'asc' + } + }; + axios.request(optionscontrato as any).then(async function (response) { + let status_internet; + let id_contrato; + status_internet = response.data?.registros[0]?.status_internet; + id_contrato = response.data?.registros[0]?.id; + if (status_internet !== 'A') { + const bodyPdf = { + text: formatBody(`*${nome}* vi tambem que a sua conexão esta bloqueada! Vou desbloquear para você.`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyPdf); + const bodyqrcode = { + text: formatBody(`Estou liberando seu acesso. Por favor aguarde!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyqrcode); + //REALIZANDO O DESBLOQUEIO + var optionsdesbloqeuio = { + method: 'POST', + url: `${urlixc}/webservice/v1/desbloqueio_confianca`, + headers: { + Authorization: `Basic ${ixckeybase64}` + }, + data: { id: id_contrato } + }; + + axios.request(optionsdesbloqeuio as any).then(async function (response) { + let tipo; + let mensagem; + tipo = response.data?.tipo; + mensagem = response.data?.mensagem; + if (tipo === 'sucesso') { + //DESCONECTANDO O CLIENTE PARA VOLTAR O ACESSO + var optionsRadius = { + method: 'GET', + url: `${urlixc}/webservice/v1/radusuarios`, + headers: { + ixcsoft: 'listar', + Authorization: `Basic ${ixckeybase64}` + }, + data: { + qtype: 'radusuarios.id_cliente', + query: id, + oper: '=', + page: '1', + rp: '1', + sortname: 'radusuarios.id', + sortorder: 'asc' + } + }; + + axios.request(optionsRadius as any).then(async function (response) { + let tipo; + tipo = response.data?.type; + if (tipo === 'success') { + const body_mensagem = { + text: formatBody(`${mensagem}`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body_mensagem); + const bodyPdf = { + text: formatBody(`Fiz os procedimentos de liberação! Agora aguarde até 5 minutos e veja se sua conexão irá retornar! .\n\nCaso não tenha voltado, retorne o contato e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyPdf); + const bodyfinaliza = { + text: formatBody(`Estamos finalizando esta conversa! Caso precise entre em contato conosco!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + } + }).catch(function (error) { + console.error(error); + }); + //FIM DA DESCONEXÃO + } else { + var msgerrolbieracao = response.data.mensagem + const bodyerro = { + text: formatBody(`Ops! Ocorreu um erro e nao consegui desbloquear`, contact), + }; + const msg_errolbieracao = { + text: formatBody(`${msgerrolbieracao}`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyerro); + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, msg_errolbieracao); + const bodyerroatendent = { + text: formatBody(`Digite *#* para voltar o menu e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyerroatendent); + } + + }).catch(async function (error) { + const bodyerro = { + text: formatBody(`Ops! Ocorreu um erro digite *#* e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyerro); + }); + } else { + const bodyfinaliza = { + text: formatBody(`Estamos finalizando esta conversa! Caso precise entre em contato conosco!`, contact), + }; + await sleep(8000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + } + + // + }).catch(async function (error) { + + const bodyerro = { + text: formatBody(`Ops! Ocorreu um erro digite *#* e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyerro); + }); + ///VE SE ESTA BLOQUEADO PARA LIBERAR! + } else { + const bodyBoleto = { + text: formatBody(`Segue a segunda-via da sua Fatura!\n\n*Fatura:* ${idboleto}\n*Nome:* ${nome}\n*Valor:* R$ ${valorCorrigido}\n*Data Vencimento:* ${datavencCorrigida}\n\nBasta clicar aqui em baixo em código de barras para copiar, apos isto basta realizar o pagamento em seu banco!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyBoleto); + const body = { + text: formatBody(`Este é o *Codigo de Barras*`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + await sleep(2000) + const body_linha_digitavel = { + text: formatBody(`${linha_digitavel}`, contact), + }; + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body_linha_digitavel); + ///VE SE ESTA BLOQUEADO PARA LIBERAR! + var optionscontrato = { + method: 'POST', + url: `${urlixc}/webservice/v1/cliente_contrato`, + headers: { + ixcsoft: 'listar', + Authorization: `Basic ${ixckeybase64}` + }, + data: { + qtype: 'cliente_contrato.id_cliente', + query: id, + oper: '=', + page: '1', + rp: '1', + sortname: 'cliente_contrato.id', + sortorder: 'asc' + } + }; + axios.request(optionscontrato as any).then(async function (response) { + let status_internet; + let id_contrato; + status_internet = response.data?.registros[0]?.status_internet; + id_contrato = response.data?.registros[0]?.id; + if (status_internet !== 'A') { + const bodyPdf = { + text: formatBody(`*${nome}* vi tambem que a sua conexão esta bloqueada! Vou desbloquear para você.`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyPdf); + const bodyqrcode = { + text: formatBody(`Estou liberando seu acesso. Por favor aguarde!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyqrcode); + //REALIZANDO O DESBLOQUEIO + var optionsdesbloqeuio = { + method: 'POST', + url: `${urlixc}/webservice/v1/desbloqueio_confianca`, + headers: { + Authorization: `Basic ${ixckeybase64}` + }, + data: { id: id_contrato } + }; + + axios.request(optionsdesbloqeuio as any).then(async function (response) { + let tipo; + let mensagem; + tipo = response.data?.tipo; + mensagem = response.data?.mensagem; + if (tipo === 'sucesso') { + //DESCONECTANDO O CLIENTE PARA VOLTAR O ACESSO + var optionsRadius = { + method: 'GET', + url: `${urlixc}/webservice/v1/radusuarios`, + headers: { + ixcsoft: 'listar', + Authorization: `Basic ${ixckeybase64}` + }, + data: { + qtype: 'radusuarios.id_cliente', + query: id, + oper: '=', + page: '1', + rp: '1', + sortname: 'radusuarios.id', + sortorder: 'asc' + } + }; + + axios.request(optionsRadius as any).then(async function (response) { + let tipo; + tipo = response.data?.type; + const body_mensagem = { + text: formatBody(`${mensagem}`, contact), + }; + if (tipo === 'success') { + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body_mensagem); + const bodyPdf = { + text: formatBody(`Fiz os procedimentos de liberação! Agora aguarde até 5 minutos e veja se sua conexão irá retornar! .\n\nCaso não tenha voltado, retorne o contato e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyPdf); + const bodyfinaliza = { + text: formatBody(`Estamos finalizando esta conversa! Caso precise entre em contato conosco!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + } else { + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body_mensagem); + const bodyPdf = { + text: formatBody(`Vou precisar que você *retire* seu equipamento da tomada.\n\n*OBS: Somente retire da tomada.* \nAguarde 1 minuto e ligue novamente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyPdf); + const bodyqrcode = { + text: formatBody(`Veja se seu acesso voltou! Caso não tenha voltado retorne o contato e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyqrcode); + const bodyfinaliza = { + text: formatBody(`Estamos finalizando esta conversa! Caso precise entre em contato conosco!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + } + }).catch(function (error) { + console.error(error); + }); + //FIM DA DESCONEXÃO + } else { + const bodyerro = { + text: formatBody(`Ops! Ocorreu um erro e nao consegui desbloquear! Digite *#* e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyerro); + } + + }).catch(async function (error) { + const bodyerro = { + text: formatBody(`Ops! Ocorreu um erro digite *#* e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyerro); + }); + } else { + const bodyfinaliza = { + text: formatBody(`Estamos finalizando esta conversa! Caso precise entre em contato conosco!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + } + + // + }).catch(async function (error) { + const bodyerro = { + text: formatBody(`Ops! Ocorreu um erro digite *#* e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyerro); + }); + ///VE SE ESTA BLOQUEADO PARA LIBERAR! + } + }).catch(function (error) { + console.error(error); + }); + //FIM DO PÌX + + + + }).catch(function (error) { + console.error(error); + }); + + } + + }).catch(async function (error) { + const body = { + text: formatBody(`*Opss!!!!*\nOcorreu um erro! Digite *#* e fale com um *Atendente*!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + }); + } else { + const body = { + text: formatBody(`Este CPF/CNPJ não é válido!\n\nPor favor tente novamente!\nOu digite *#* para voltar ao *Menu Anterior*`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + } + } + } + + + } + } + + if (filaescolhida === "Religue de Confiança" || filaescolhida === "Liberação em Confiança") { + let cpfcnpj + cpfcnpj = getBodyMessage(msg); + cpfcnpj = cpfcnpj.replace(/\./g, ''); + cpfcnpj = cpfcnpj.replace('-', '') + cpfcnpj = cpfcnpj.replace('/', '') + cpfcnpj = cpfcnpj.replace(' ', '') + cpfcnpj = cpfcnpj.replace(',', '') + + const asaastoken = await Setting.findOne({ + where: { + key: "asaas", + companyId + } + }); + const ixcapikey = await Setting.findOne({ + where: { + key: "tokenixc", + companyId + } + }); + const urlixcdb = await Setting.findOne({ + where: { + key: "ipixc", + companyId + } + }); + const ipmkauth = await Setting.findOne({ + where: { + key: "ipmkauth", + companyId + } + }); + const clientidmkauth = await Setting.findOne({ + where: { + key: "clientidmkauth", + companyId + } + }); + const clientesecretmkauth = await Setting.findOne({ + where: { + key: "clientsecretmkauth", + companyId + } + }); + + let urlmkauth = ipmkauth.value + if (urlmkauth.substr(-1) === '/') { + urlmkauth = urlmkauth.slice(0, -1); + } + + //VARS + let url = `${urlmkauth}/api/`; + const Client_Id = clientidmkauth.value + const Client_Secret = clientesecretmkauth.value + const ixckeybase64 = btoa(ixcapikey.value); + const urlixc = urlixcdb.value + const asaastk = asaastoken.value + + const cnpj_cpf = getBodyMessage(msg); + let numberCPFCNPJ = cpfcnpj; + + if (ixcapikey.value != "" && urlixcdb.value != "") { + if (isNumeric(numberCPFCNPJ) === true) { + if (cpfcnpj.length > 2) { + const isCPFCNPJ = validaCpfCnpj(numberCPFCNPJ) + if (isCPFCNPJ) { + if (numberCPFCNPJ.length <= 11) { + numberCPFCNPJ = numberCPFCNPJ.replace(/(\d{3})(\d)/, "$1.$2") + numberCPFCNPJ = numberCPFCNPJ.replace(/(\d{3})(\d)/, "$1.$2") + numberCPFCNPJ = numberCPFCNPJ.replace(/(\d{3})(\d{1,2})$/, "$1-$2") + } else { + numberCPFCNPJ = numberCPFCNPJ.replace(/^(\d{2})(\d)/, "$1.$2") + numberCPFCNPJ = numberCPFCNPJ.replace(/^(\d{2})\.(\d{3})(\d)/, "$1.$2.$3") + numberCPFCNPJ = numberCPFCNPJ.replace(/\.(\d{3})(\d)/, ".$1/$2") + numberCPFCNPJ = numberCPFCNPJ.replace(/(\d{4})(\d)/, "$1-$2") + } + //const token = await CheckSettingsHelper("OBTEM O TOKEN DO BANCO (dei insert na tabela settings)") + const body = { + text: formatBody(`Aguarde! Estamos consultando na base de dados!`, contact), + }; + try { + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + } catch (error) { + + } + var options = { + method: 'GET', + url: `${urlixc}/webservice/v1/cliente`, + headers: { + ixcsoft: 'listar', + Authorization: `Basic ${ixckeybase64}` + }, + data: { + qtype: 'cliente.cnpj_cpf', + query: numberCPFCNPJ, + oper: '=', + page: '1', + rp: '1', + sortname: 'cliente.cnpj_cpf', + sortorder: 'asc' + } + }; + + axios.request(options as any).then(async function (response) { + + if (response.data.type === 'error') { + const body = { + text: formatBody(`*Opss!!!!*\nOcorreu um erro! Digite *#* e fale com um *Atendente*!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + } if (response.data.total === 0) { + const body = { + text: formatBody(`Cadastro não localizado! *CPF/CNPJ* incorreto ou inválido. Tenta novamente!`, contact), + }; + try { + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + } catch (error) { + + } + } else { + + let nome; + let id; + let type; + + nome = response.data?.registros[0]?.razao + id = response.data?.registros[0]?.id + type = response.data?.type + + + const body = { + text: formatBody(`Localizei seu Cadastro! \n*${nome}* só mais um instante por favor!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + ///VE SE ESTA BLOQUEADO PARA LIBERAR! + var optionscontrato = { + method: 'POST', + url: `${urlixc}/webservice/v1/cliente_contrato`, + headers: { + ixcsoft: 'listar', + Authorization: `Basic ${ixckeybase64}` + }, + data: { + qtype: 'cliente_contrato.id_cliente', + query: id, + oper: '=', + page: '1', + rp: '1', + sortname: 'cliente_contrato.id', + sortorder: 'asc' + } + }; + axios.request(optionscontrato as any).then(async function (response) { + let status_internet; + let id_contrato; + status_internet = response.data?.registros[0]?.status_internet; + id_contrato = response.data?.registros[0]?.id; + if (status_internet !== 'A') { + const bodyPdf = { + text: formatBody(`*${nome}* a sua conexão esta bloqueada! Vou desbloquear para você.`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyPdf); + const bodyqrcode = { + text: formatBody(`Estou liberando seu acesso. Por favor aguarde!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyqrcode); + //REALIZANDO O DESBLOQUEIO + var optionsdesbloqeuio = { + method: 'POST', + url: `${urlixc}/webservice/v1/desbloqueio_confianca`, + headers: { + Authorization: `Basic ${ixckeybase64}` + }, + data: { id: id_contrato } + }; + + axios.request(optionsdesbloqeuio as any).then(async function (response) { + let tipo; + let mensagem; + tipo = response.data?.tipo; + mensagem = response.data?.mensagem; + const body_mensagem = { + text: formatBody(`${mensagem}`, contact), + }; + if (tipo === 'sucesso') { + //DESCONECTANDO O CLIENTE PARA VOLTAR O ACESSO + var optionsRadius = { + method: 'GET', + url: `${urlixc}/webservice/v1/radusuarios`, + headers: { + ixcsoft: 'listar', + Authorization: `Basic ${ixckeybase64}` + }, + data: { + qtype: 'radusuarios.id_cliente', + query: id, + oper: '=', + page: '1', + rp: '1', + sortname: 'radusuarios.id', + sortorder: 'asc' + } + }; + + axios.request(optionsRadius as any).then(async function (response) { + let tipo; + tipo = response.data?.type; + + if (tipo === 'success') { + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body_mensagem); + const bodyPdf = { + text: formatBody(`Fiz os procedimentos de liberação! Agora aguarde até 5 minutos e veja se sua conexão irá retornar! .\n\nCaso não tenha voltado, retorne o contato e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyPdf); + const bodyfinaliza = { + text: formatBody(`Estamos finalizando esta conversa! Caso precise entre em contato conosco!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + } else { + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body_mensagem); + const bodyPdf = { + text: formatBody(`Vou precisar que você *retire* seu equipamento da tomada.\n\n*OBS: Somente retire da tomada.* \nAguarde 1 minuto e ligue novamente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyPdf); + const bodyqrcode = { + text: formatBody(`Veja se seu acesso voltou! Caso não tenha voltado retorne o contato e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyqrcode); + const bodyfinaliza = { + text: formatBody(`Estamos finalizando esta conversa! Caso precise entre em contato conosco!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + } + }).catch(function (error) { + console.error(error); + }); + //FIM DA DESCONEXÃO + + } else { + const bodyerro = { + text: formatBody(`Ops! Ocorreu um erro e nao consegui desbloquear!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyerro); + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body_mensagem); + const bodyerroatendente = { + text: formatBody(`Digite *#* e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyerroatendente); + } /* else { + const bodyerro = { + text: formatBody(`Ops! Ocorreu um erro e nao consegui desbloquear! Digite *#* e fale com um atendente!` + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`,bodyerro); + } */ + + }).catch(async function (error) { + + const bodyerro = { + text: formatBody(`Ops! Ocorreu um erro digite *#* e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyerro); + }); + } else { + const bodysembloqueio = { + text: formatBody(`Sua Conexão não está bloqueada! Caso esteja com dificuldades de navegação, retorne o contato e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodysembloqueio); + const bodyfinaliza = { + text: formatBody(`Estamos finalizando esta conversa! Caso precise entre em contato conosco!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyfinaliza); + await UpdateTicketService({ + ticketData: { status: "closed" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + } + + // + }).catch(async function (error) { + + const bodyerro = { + text: formatBody(`Ops! Ocorreu um erro digite *#* e fale com um atendente!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, bodyerro); + }); + + } + + }).catch(async function (error) { + const body = { + text: formatBody(`*Opss!!!!*\nOcorreu um erro! Digite *#* e fale com um *Atendente*!`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + }); + } else { + const body = { + text: formatBody(`Este CPF/CNPJ não é válido!\n\nPor favor tente novamente!\nOu digite *#* para voltar ao *Menu Anterior*`, contact), + }; + await sleep(2000) + await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, body); + } + } + } + } + } + +} diff --git a/backend/src/services/WbotServices/wbotClosedTickets.ts b/backend/src/services/WbotServices/wbotClosedTickets.ts new file mode 100644 index 0000000..b29d41a --- /dev/null +++ b/backend/src/services/WbotServices/wbotClosedTickets.ts @@ -0,0 +1,118 @@ +import { Op } from "sequelize"; +import Ticket from "../../models/Ticket" +import Whatsapp from "../../models/Whatsapp" +import { getIO } from "../../libs/socket" +import formatBody from "../../helpers/Mustache"; +import SendWhatsAppMessage from "./SendWhatsAppMessage"; +import moment from "moment"; +import ShowTicketService from "../TicketServices/ShowTicketService"; +import { verifyMessage } from "./wbotMessageListener"; +import TicketTraking from "../../models/TicketTraking"; + +export const ClosedAllOpenTickets = async (companyId: number): Promise => { + + // @ts-ignore: Unreachable code error + const closeTicket = async (ticket: any, currentStatus: any, body: any) => { + if (currentStatus === 'nps') { + + await ticket.update({ + status: "closed", + //userId: ticket.userId || null, + lastMessage: body, + unreadMessages: 0, + amountUseBotQueues: 0 + }); + + } else if (currentStatus === 'open') { + + await ticket.update({ + status: "closed", + // userId: ticket.userId || null, + lastMessage: body, + unreadMessages: 0, + amountUseBotQueues: 0 + }); + + } else { + + await ticket.update({ + status: "closed", + //userId: ticket.userId || null, + unreadMessages: 0 + }); + } + }; + + const io = getIO(); + try { + + const { rows: tickets } = await Ticket.findAndCountAll({ + where: { status: { [Op.in]: ["open"] }, companyId }, + order: [["updatedAt", "DESC"]] + }); + + tickets.forEach(async ticket => { + const showTicket = await ShowTicketService(ticket.id, companyId); + const whatsapp = await Whatsapp.findByPk(showTicket?.whatsappId); + const ticketTraking = await TicketTraking.findOne({ + where: { + ticketId: ticket.id, + finishedAt: null, + } + }) + + if (!whatsapp) return; + + let { + expiresInactiveMessage, //mensage de encerramento por inatividade + expiresTicket //tempo em horas para fechar ticket automaticamente + } = whatsapp + + + // @ts-ignore: Unreachable code error + if (expiresTicket && expiresTicket !== "" && + // @ts-ignore: Unreachable code error + expiresTicket !== "0" && Number(expiresTicket) > 0) { + + //mensagem de encerramento por inatividade + const bodyExpiresMessageInactive = formatBody(`\u200e ${expiresInactiveMessage}`, showTicket.contact); + + const dataLimite = new Date() + dataLimite.setMinutes(dataLimite.getMinutes() - Number(expiresTicket)); + + if (showTicket.status === "open" && !showTicket.isGroup) { + + const dataUltimaInteracaoChamado = new Date(showTicket.updatedAt) + + if (dataUltimaInteracaoChamado < dataLimite && showTicket.fromMe) { + + closeTicket(showTicket, showTicket.status, bodyExpiresMessageInactive); + + if (expiresInactiveMessage !== "" && expiresInactiveMessage !== undefined) { + const sentMessage = await SendWhatsAppMessage({ body: bodyExpiresMessageInactive, ticket: showTicket }); + + await verifyMessage(sentMessage, showTicket, showTicket.contact); + } + + await ticketTraking.update({ + finishedAt: moment().toDate(), + closedAt: moment().toDate(), + whatsappId: ticket.whatsappId, + userId: ticket.userId, + }) + + io.to("open").emit(`company-${companyId}-ticket`, { + action: "delete", + ticketId: showTicket.id + }); + + } + } + } + }); + + } catch (e: any) { + console.log('e', e) + } + +} diff --git a/backend/src/services/WbotServices/wbotGetMessageFromType.ts b/backend/src/services/WbotServices/wbotGetMessageFromType.ts new file mode 100644 index 0000000..ce4620f --- /dev/null +++ b/backend/src/services/WbotServices/wbotGetMessageFromType.ts @@ -0,0 +1,128 @@ +import { proto } from "@whiskeysockets/baileys"; + +// Função para extrair informações de mensagens de texto +export const getTextMessage = (msg: proto.IWebMessageInfo) => { + return msg.message?.conversation; +}; + +// Função para extrair informações de mensagens de imagem +export const getImageMessage = (msg: proto.IWebMessageInfo) => { + return msg.message?.imageMessage?.caption || "Imagem"; +}; + +// Função para extrair informações de mensagens de vídeo +export const getVideoMessage = (msg: proto.IWebMessageInfo) => { + return msg.message?.videoMessage?.caption || "Vídeo"; +}; + +// Função para extrair informações de mensagens de áudio +export const getAudioMessage = (msg: proto.IWebMessageInfo) => { + return "Áudio"; +}; + +// Função para extrair informações de mensagens de documento +export const getDocumentMessage = (msg: proto.IWebMessageInfo) => { + return msg.message?.documentMessage?.fileName || "Documento"; +}; + +// Função para extrair informações de mensagens de localização +export const getLocationMessage = (msg: proto.IWebMessageInfo) => { + return { + latitude: msg.message?.locationMessage?.degreesLatitude, + longitude: msg.message?.locationMessage?.degreesLongitude + }; +}; + +// Função para extrair informações de mensagens de contato +export const getContactMessage = (msg: proto.IWebMessageInfo) => { + return msg.message?.contactMessage?.displayName; +}; + +// Função para extrair informações de mensagens de botão +export const getButtonsMessage = (msg: proto.IWebMessageInfo) => { + return msg.message?.buttonsResponseMessage?.selectedButtonId; +}; + +// Função para extrair informações de mensagens de lista +export const getListMessage = (msg: proto.IWebMessageInfo) => { + return msg.message?.listResponseMessage?.singleSelectReply?.selectedRowId; +}; + +// Função para extrair informações de mensagens de reação +export const getReactionMessage = (msg: proto.IWebMessageInfo) => { + return msg.message?.reactionMessage?.text; +}; + +// Função para extrair informações de mensagens de adesivo (sticker) +export const getStickerMessage = (msg: proto.IWebMessageInfo) => { + return msg.message?.stickerMessage; +}; + +// Função para extrair informações de mensagens de modelo (template) +export const getTemplateMessage = (msg: proto.IWebMessageInfo) => { + return msg.message?.templateMessage?.hydratedTemplate?.hydratedContentText; +}; + +// Função para extrair informações de mensagens de pagamento +export const getPaymentMessage = (msg: proto.IWebMessageInfo) => { + return msg.message?.sendPaymentMessage?.noteMessage; +}; + +// Função para extrair informações de mensagens de convite de grupo +export const getGroupInviteMessage = (msg: proto.IWebMessageInfo) => { + return msg.message?.groupInviteMessage?.groupName; +}; + +// Função para extrair informações de mensagens de chamada +export const getCallMessage = (msg: proto.IWebMessageInfo) => { + return msg.message?.bcallMessage?.sessionId; +}; + +export const getViewOnceMessage = (msg: proto.IWebMessageInfo): string => { + if (msg.key.fromMe && msg?.message?.viewOnceMessage?.message?.buttonsMessage?.contentText) { + let bodyMessage = `*${msg?.message?.viewOnceMessage?.message?.buttonsMessage?.contentText}*`; + for (const buton of msg.message?.viewOnceMessage?.message?.buttonsMessage?.buttons) { + bodyMessage += `\n\n${buton.buttonText?.displayText}`; + } + return bodyMessage; + } + if (msg.key.fromMe && msg?.message?.viewOnceMessage?.message?.listMessage) { + let bodyMessage = `*${msg?.message?.viewOnceMessage?.message?.listMessage?.description}*`; + for (const buton of msg.message?.viewOnceMessage?.message?.listMessage?.sections) { + for (const rows of buton.rows) { + bodyMessage += `\n\n${rows.title}`; + } + } + return bodyMessage; + } +}; + +export const getAd = (msg: proto.IWebMessageInfo): string => { + if (msg.key.fromMe && msg.message?.listResponseMessage?.contextInfo?.externalAdReply) { + let bodyMessage = `*${msg.message?.listResponseMessage?.contextInfo?.externalAdReply?.title}*`; + bodyMessage += `\n\n${msg.message?.listResponseMessage?.contextInfo?.externalAdReply?.body}`; + return bodyMessage; + } +}; + +export const getBodyButton = (msg: proto.IWebMessageInfo): string => { + if (msg.key.fromMe && msg?.message?.viewOnceMessage?.message?.buttonsMessage?.contentText) { + let bodyMessage = `*${msg?.message?.viewOnceMessage?.message?.buttonsMessage?.contentText}*`; + + for (const buton of msg.message?.viewOnceMessage?.message?.buttonsMessage?.buttons) { + bodyMessage += `\n\n${buton.buttonText?.displayText}`; + } + return bodyMessage; + } + + if (msg.key.fromMe && msg?.message?.viewOnceMessage?.message?.listMessage) { + let bodyMessage = `*${msg?.message?.viewOnceMessage?.message?.listMessage?.description}*`; + for (const buton of msg.message?.viewOnceMessage?.message?.listMessage?.sections) { + for (const rows of buton.rows) { + bodyMessage += `\n\n${rows.title}`; + } + } + + return bodyMessage; + } +}; diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts new file mode 100644 index 0000000..bcf0fcd --- /dev/null +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -0,0 +1,2602 @@ +import * as Sentry from "@sentry/node"; +import { writeFile } from "fs"; +import { head, isNil } from "lodash"; +import path, { join } from "path"; +import { promisify } from "util"; + +import { map_msg } from "../../utils/global"; + +import { + downloadMediaMessage, + extractMessageContent, + getContentType, + jidNormalizedUser, + MessageUpsertType, + proto, + WAMessage, + WAMessageStubType, + WAMessageUpdate, + delay, + WASocket, +} from "@whiskeysockets/baileys"; +import Contact from "../../models/Contact"; +import Message from "../../models/Message"; +import Ticket from "../../models/Ticket"; +import { Mutex } from "async-mutex"; + +import { + AudioConfig, + SpeechConfig, + SpeechSynthesizer +} from "microsoft-cognitiveservices-speech-sdk"; +import moment from "moment"; +import { ChatCompletionRequestMessage, Configuration, OpenAIApi } from "openai"; +import { Op } from "sequelize"; +import { debounce } from "../../helpers/Debounce"; +import formatBody from "../../helpers/Mustache"; +import ffmpeg from "fluent-ffmpeg"; +import { cacheLayer } from "../../libs/cache"; +import { getIO } from "../../libs/socket"; +import { Store } from "../../libs/store"; +import MarkDeleteWhatsAppMessage from "./MarkDeleteWhatsAppMessage"; +import Campaign from "../../models/Campaign"; +import * as MessageUtils from "./wbotGetMessageFromType"; +import CampaignShipping from "../../models/CampaignShipping"; +import Queue from "../../models/Queue"; +import QueueIntegrations from "../../models/QueueIntegrations"; +import QueueOption from "../../models/QueueOption"; +import Setting from "../../models/Setting"; +import TicketTraking from "../../models/TicketTraking"; +import User from "../../models/User"; +import UserRating from "../../models/UserRating"; +import { campaignQueue, parseToMilliseconds, randomValue } from "../../queues"; +import { logger } from "../../utils/logger"; +import VerifyCurrentSchedule from "../CompanyService/VerifyCurrentSchedule"; +import CreateOrUpdateContactService from "../ContactServices/CreateOrUpdateContactService"; +import CreateMessageService from "../MessageServices/CreateMessageService"; +import ShowQueueIntegrationService from "../QueueIntegrationServices/ShowQueueIntegrationService"; +import FindOrCreateATicketTrakingService from "../TicketServices/FindOrCreateATicketTrakingService"; +import FindOrCreateTicketService from "../TicketServices/FindOrCreateTicketService"; +import UpdateTicketService from "../TicketServices/UpdateTicketService"; +import typebotListener from "../TypebotServices/typebotListener"; +import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService"; +import { provider } from "./providers"; +import { SimpleObjectCache } from "../../helpers/simpleObjectCache"; +import SendWhatsAppMessage from "./SendWhatsAppMessage"; +import { getMessageOptions } from "./SendWhatsAppMedia"; + + +import ffmpegPath from 'ffmpeg-static'; +ffmpeg.setFfmpegPath(ffmpegPath); + +const request = require("request"); + +const fs = require('fs') + +type Session = WASocket & { + id?: number; + store?: Store; +}; + +interface SessionOpenAi extends OpenAIApi { + id?: number; +} + +const sessionsOpenAi: SessionOpenAi[] = []; + +interface ImessageUpsert { + messages: proto.IWebMessageInfo[]; + type: MessageUpsertType; +} + +interface IMe { + name: string; + id: string; +} + +interface IMessage { + messages: WAMessage[]; + isLatest: boolean; +} + +export const isNumeric = (value: string) => /^-?\d+$/.test(value); + +const writeFileAsync = promisify(writeFile); + +const wbotMutex = new Mutex(); + +const groupContactCache = new SimpleObjectCache(1000 * 30, logger); + +const multVecardGet = function (param: any) { + let output = " " + + let name = param.split("\n")[2].replace(";;;", "\n").replace('N:', "").replace(";", "").replace(";", " ").replace(";;", " ").replace("\n", "") + let inicio = param.split("\n")[4].indexOf('=') + let fim = param.split("\n")[4].indexOf(':') + let contact = param.split("\n")[4].substring(inicio + 1, fim).replace(";", "") + let contactSemWhats = param.split("\n")[4].replace("item1.TEL:", "") + + if (contact != "item1.TEL") { + output = output + name + ": 📞" + contact + "" + "\n" + } else + output = output + name + ": 📞" + contactSemWhats + "" + "\n" + return output +} + +const contactsArrayMessageGet = (msg: any,) => { + let contactsArray = msg.message?.contactsArrayMessage?.contacts + let vcardMulti = contactsArray.map(function (item, indice) { + return item.vcard; + }); + + let bodymessage = `` + vcardMulti.forEach(function (vcard, indice) { + bodymessage += vcard + "\n\n" + "" + }) + + let contacts = bodymessage.split("BEGIN:") + + contacts.shift() + let finalContacts = "" + for (let contact of contacts) { + finalContacts = finalContacts + multVecardGet(contact) + } + + return finalContacts +} + +const getTypeMessage = (msg: proto.IWebMessageInfo): string => { + return getContentType(msg.message); +}; + +export function validaCpfCnpj(val) { + if (val.length == 11) { + var cpf = val.trim(); + + cpf = cpf.replace(/\./g, ''); + cpf = cpf.replace('-', ''); + cpf = cpf.split(''); + + var v1 = 0; + var v2 = 0; + var aux = false; + + for (var i = 1; cpf.length > i; i++) { + if (cpf[i - 1] != cpf[i]) { + aux = true; + } + } + + if (aux == false) { + return false; + } + + for (var i = 0, p = 10; (cpf.length - 2) > i; i++, p--) { + v1 += cpf[i] * p; + } + + v1 = ((v1 * 10) % 11); + + if (v1 == 10) { + v1 = 0; + } + + if (v1 != cpf[9]) { + return false; + } + + for (var i = 0, p = 11; (cpf.length - 1) > i; i++, p--) { + v2 += cpf[i] * p; + } + + v2 = ((v2 * 10) % 11); + + if (v2 == 10) { + v2 = 0; + } + + if (v2 != cpf[10]) { + return false; + } else { + return true; + } + } else if (val.length == 14) { + var cnpj = val.trim(); + + cnpj = cnpj.replace(/\./g, ''); + cnpj = cnpj.replace('-', ''); + cnpj = cnpj.replace('/', ''); + cnpj = cnpj.split(''); + + var v1 = 0; + var v2 = 0; + var aux = false; + + for (var i = 1; cnpj.length > i; i++) { + if (cnpj[i - 1] != cnpj[i]) { + aux = true; + } + } + + if (aux == false) { + return false; + } + + for (var i = 0, p1 = 5, p2 = 13; (cnpj.length - 2) > i; i++, p1--, p2--) { + if (p1 >= 2) { + v1 += cnpj[i] * p1; + } else { + v1 += cnpj[i] * p2; + } + } + + v1 = (v1 % 11); + + if (v1 < 2) { + v1 = 0; + } else { + v1 = (11 - v1); + } + + if (v1 != cnpj[12]) { + return false; + } + + for (var i = 0, p1 = 6, p2 = 14; (cnpj.length - 1) > i; i++, p1--, p2--) { + if (p1 >= 2) { + v2 += cnpj[i] * p1; + } else { + v2 += cnpj[i] * p2; + } + } + + v2 = (v2 % 11); + + if (v2 < 2) { + v2 = 0; + } else { + v2 = (11 - v2); + } + + if (v2 != cnpj[13]) { + return false; + } else { + return true; + } + } else { + return false; + } +} + +function timeout(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +export async function sleep(time) { + await timeout(time); +} +export const sendMessageImage = async ( + wbot: Session, + contact, + ticket: Ticket, + url: string, + caption: string +) => { + + let sentMessage + try { + sentMessage = await wbot.sendMessage( + `${contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + { + image: url ? { url } : fs.readFileSync(`public/temp/${caption}-${makeid(10)}`), + fileName: caption, + caption: caption, + mimetype: 'image/jpeg' + } + ); + } catch (error) { + sentMessage = await wbot.sendMessage( + `${contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + { + text: formatBody('Não consegui enviar o PDF, tente novamente!', contact) + } + ); + } + verifyMessage(sentMessage, ticket, contact); +}; + +export const sendMessageLink = async ( + wbot: Session, + contact: Contact, + ticket: Ticket, + url: string, + caption: string +) => { + + let sentMessage + try { + sentMessage = await wbot.sendMessage( + `${contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, { + document: url ? { url } : fs.readFileSync(`public/temp/${caption}-${makeid(10)}`), + fileName: caption, + caption: caption, + mimetype: 'application/pdf' + } + ); + } catch (error) { + sentMessage = await wbot.sendMessage( + `${contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, { + text: formatBody('Não consegui enviar o PDF, tente novamente!', contact) + } + ); + } + verifyMessage(sentMessage, ticket, contact); +}; + +export function makeid(length) { + var result = ''; + var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + var charactersLength = characters.length; + for (var i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; +} + + +const getBodyButton = (msg: proto.IWebMessageInfo): string => { + if (msg.key.fromMe && msg?.message?.viewOnceMessage?.message?.buttonsMessage?.contentText) { + let bodyMessage = `*${msg?.message?.viewOnceMessage?.message?.buttonsMessage?.contentText}*`; + + for (const buton of msg.message?.viewOnceMessage?.message?.buttonsMessage?.buttons) { + bodyMessage += `\n\n${buton.buttonText?.displayText}`; + } + return bodyMessage; + } + + if (msg.key.fromMe && msg?.message?.viewOnceMessage?.message?.listMessage) { + let bodyMessage = `*${msg?.message?.viewOnceMessage?.message?.listMessage?.description}*`; + for (const buton of msg.message?.viewOnceMessage?.message?.listMessage?.sections) { + for (const rows of buton.rows) { + bodyMessage += `\n\n${rows.title}`; + } + } + + return bodyMessage; + } +}; + +const msgLocation = (image, latitude, longitude) => { + if (image) { + var b64 = Buffer.from(image).toString("base64"); + + let data = `data:image/png;base64, ${b64} | https://maps.google.com/maps?q=${latitude}%2C${longitude}&z=17&hl=pt-BR|${latitude}, ${longitude} `; + return data; + } +}; + +export const getBodyMessage = (msg: proto.IWebMessageInfo): string | null => { + + try { + let type = getTypeMessage(msg); + + const types = { + conversation: msg?.message?.conversation, + editedMessage: msg?.message?.editedMessage?.message?.protocolMessage?.editedMessage?.conversation, + imageMessage: msg.message?.imageMessage?.caption, + videoMessage: msg.message?.videoMessage?.caption, + extendedTextMessage: msg.message?.extendedTextMessage?.text, + buttonsResponseMessage: msg.message?.buttonsResponseMessage?.selectedButtonId, + templateButtonReplyMessage: msg.message?.templateButtonReplyMessage?.selectedId, + messageContextInfo: msg.message?.buttonsResponseMessage?.selectedButtonId || msg.message?.listResponseMessage?.title, + buttonsMessage: getBodyButton(msg) || msg.message?.listResponseMessage?.singleSelectReply?.selectedRowId, + viewOnceMessage: getBodyButton(msg) || msg.message?.listResponseMessage?.singleSelectReply?.selectedRowId, + stickerMessage: "sticker", + reactionMessage: MessageUtils.getReactionMessage(msg) || "reaction", + contactMessage: msg.message?.contactMessage?.vcard, + contactsArrayMessage: (msg.message?.contactsArrayMessage?.contacts) && contactsArrayMessageGet(msg), + //locationMessage: `Latitude: ${msg.message.locationMessage?.degreesLatitude} - Longitude: ${msg.message.locationMessage?.degreesLongitude}`, + locationMessage: msgLocation( + msg.message?.locationMessage?.jpegThumbnail, + msg.message?.locationMessage?.degreesLatitude, + msg.message?.locationMessage?.degreesLongitude + ), + liveLocationMessage: `Latitude: ${msg.message?.liveLocationMessage?.degreesLatitude} - Longitude: ${msg.message?.liveLocationMessage?.degreesLongitude}`, + documentMessage: msg.message?.documentMessage?.title, + documentWithCaptionMessage: msg.message?.documentWithCaptionMessage?.message?.documentMessage?.caption, + audioMessage: "Áudio", + listMessage: getBodyButton(msg) || msg.message?.listResponseMessage?.title, + listResponseMessage: msg.message?.listResponseMessage?.singleSelectReply?.selectedRowId, + }; + + const objKey = Object.keys(types).find(key => key === type); + + if (!objKey) { + logger.warn(`#### Nao achou o type 152: ${type} +${JSON.stringify(msg)}`); + Sentry.setExtra("Mensagem", { BodyMsg: msg.message, msg, type }); + Sentry.captureException( + new Error("Novo Tipo de Mensagem em getTypeMessage") + ); + } + return types[type]; + } catch (error) { + Sentry.setExtra("Error getTypeMessage", { msg, BodyMsg: msg.message }); + Sentry.captureException(error); + console.log(error); + } +}; + + +export const getQuotedMessage = (msg: proto.IWebMessageInfo): any => { + const body = + msg.message.imageMessage.contextInfo || + msg.message.videoMessage.contextInfo || + msg.message?.documentMessage || + msg.message.extendedTextMessage.contextInfo || + msg.message.buttonsResponseMessage.contextInfo || + msg.message.listResponseMessage.contextInfo || + msg.message.templateButtonReplyMessage.contextInfo || + msg.message.buttonsResponseMessage?.contextInfo || + msg?.message?.buttonsResponseMessage?.selectedButtonId || + msg.message.listResponseMessage?.singleSelectReply?.selectedRowId || + msg?.message?.listResponseMessage?.singleSelectReply.selectedRowId || + msg.message.listResponseMessage?.contextInfo; + msg.message.senderKeyDistributionMessage; + + // testar isso + + return extractMessageContent(body[Object.keys(body).values().next().value]); +}; +export const getQuotedMessageId = (msg: proto.IWebMessageInfo) => { + const body = extractMessageContent(msg.message)[ + Object.keys(msg?.message).values().next().value + ]; + let reaction = msg?.message?.reactionMessage + ? msg?.message?.reactionMessage?.key?.id + : ""; + + return reaction ? reaction : body?.contextInfo?.stanzaId; +}; + +const getMeSocket = (wbot: Session): IMe => { + return { + id: jidNormalizedUser((wbot as WASocket).user.id), + name: (wbot as WASocket).user.name + } +}; + +const getSenderMessage = ( + msg: proto.IWebMessageInfo, + wbot: Session +): string => { + const me = getMeSocket(wbot); + if (msg.key.fromMe) return me.id; + + const senderId = msg.participant || msg.key.participant || msg.key.remoteJid || undefined; + + return senderId && jidNormalizedUser(senderId); +}; + +const getContactMessage = async (msg: proto.IWebMessageInfo, wbot: Session) => { + const isGroup = msg.key.remoteJid.includes("g.us"); + const rawNumber = msg.key.remoteJid.replace(/\D/g, ""); + return isGroup + ? { + id: getSenderMessage(msg, wbot), + name: msg.pushName + } + : { + id: msg.key.remoteJid, + name: msg.key.fromMe ? rawNumber : msg.pushName + }; +}; + +const downloadMedia = async (msg: proto.IWebMessageInfo) => { + + let buffer + try { + buffer = await downloadMediaMessage( + msg, + 'buffer', + {} + ) + } catch (err) { + + + console.error('Erro ao baixar mídia:', err); + + // Trate o erro de acordo com as suas necessidades + } + + let filename = msg.message?.documentMessage?.fileName || ""; + + const mineType = + msg.message?.imageMessage || + msg.message?.audioMessage || + msg.message?.videoMessage || + msg.message?.stickerMessage || + msg.message?.documentMessage || + msg.message?.documentWithCaptionMessage?.message?.documentMessage || + msg.message?.extendedTextMessage?.contextInfo?.quotedMessage?.imageMessage || + msg.message?.extendedTextMessage?.contextInfo?.quotedMessage?.videoMessage; + + if (!mineType) + console.log(msg) + + if (!filename) { + const ext = mineType.mimetype.split("/")[1].split(";")[0]; + filename = `${new Date().getTime()}.${ext}`; + } else { + filename = `${new Date().getTime()}_${filename}`; + } + + const media = { + data: buffer, + mimetype: mineType.mimetype, + filename + }; + + return media; +} + + +const verifyContact = async ( + msgContact: IMe, + wbot: Session, + companyId: number +): Promise => { + let profilePicUrl: string; + try { + profilePicUrl = await wbot.profilePictureUrl(msgContact.id); + } catch (e) { + Sentry.captureException(e); + profilePicUrl = `${process.env.FRONTEND_URL}/nopicture.png`; + } + + const contactData = { + name: msgContact?.name || msgContact.id.replace(/\D/g, ""), + number: msgContact.id.replace(/\D/g, ""), + profilePicUrl, + isGroup: msgContact.id.includes("g.us"), + companyId, + whatsappId: wbot.id + }; + + + + const contact = CreateOrUpdateContactService(contactData); + + return contact; +}; + +const verifyQuotedMessage = async ( + msg: proto.IWebMessageInfo +): Promise => { + if (!msg) return null; + const quoted = getQuotedMessageId(msg); + + if (!quoted) return null; + + const quotedMsg = await Message.findOne({ + where: { id: quoted }, + }); + + if (!quotedMsg) return null; + + return quotedMsg; +}; + +const sanitizeName = (name: string): string => { + let sanitized = name.split(" ")[0]; + sanitized = sanitized.replace(/[^a-zA-Z0-9]/g, ""); + return sanitized.substring(0, 60); +}; +const convertTextToSpeechAndSaveToFile = ( + text: string, + filename: string, + subscriptionKey: string, + serviceRegion: string, + voice: string = "pt-BR-FabioNeural", + audioToFormat: string = "mp3" +): Promise => { + return new Promise((resolve, reject) => { + const speechConfig = SpeechConfig.fromSubscription( + subscriptionKey, + serviceRegion + ); + speechConfig.speechSynthesisVoiceName = voice; + const audioConfig = AudioConfig.fromAudioFileOutput(`${filename}.wav`); + const synthesizer = new SpeechSynthesizer(speechConfig, audioConfig); + synthesizer.speakTextAsync( + text, + result => { + if (result) { + convertWavToAnotherFormat( + `${filename}.wav`, + `${filename}.${audioToFormat}`, + audioToFormat + ) + .then(output => { + resolve(); + }) + .catch(error => { + console.error(error); + reject(error); + }); + } else { + reject(new Error("No result from synthesizer")); + } + synthesizer.close(); + }, + error => { + console.error(`Error: ${error}`); + synthesizer.close(); + reject(error); + } + ); + }); +}; + +const convertWavToAnotherFormat = ( + inputPath: string, + outputPath: string, + toFormat: string +) => { + return new Promise((resolve, reject) => { + ffmpeg() + .input(inputPath) + .toFormat(toFormat) + .on("end", () => resolve(outputPath)) + .on("error", (err: { message: any }) => + reject(new Error(`Error converting file: ${err.message}`)) + ) + .save(outputPath); + }); +}; + +const deleteFileSync = (path: string): void => { + try { + fs.unlinkSync(path); + } catch (error) { + console.error("Erro ao deletar o arquivo:", error); + } +}; + +const keepOnlySpecifiedChars = (str: string) => { + return str.replace(/[^a-zA-Z0-9áéíóúÁÉÍÓÚâêîôûÂÊÎÔÛãõÃÕçÇ!?.,;:\s]/g, ""); +}; +const handleOpenAi = async ( + msg: proto.IWebMessageInfo, + wbot: Session, + ticket: Ticket, + contact: Contact, + mediaSent: Message | undefined +): Promise => { + const bodyMessage = getBodyMessage(msg); + + if (!bodyMessage) return; + + + let { prompt } = await ShowWhatsAppService(wbot.id, ticket.companyId); + + + if (!prompt && !isNil(ticket?.queue?.prompt)) { + prompt = ticket.queue.prompt; + } + + if (!prompt) return; + + if (msg.messageStubType) return; + + const publicFolder: string = path.resolve( + __dirname, + "..", + "..", + "..", + "public" + ); + + let openai: SessionOpenAi; + const openAiIndex = sessionsOpenAi.findIndex(s => s.id === wbot.id); + + + if (openAiIndex === -1) { + const configuration = new Configuration({ + apiKey: prompt.apiKey + }); + openai = new OpenAIApi(configuration); + openai.id = wbot.id; + sessionsOpenAi.push(openai); + } else { + openai = sessionsOpenAi[openAiIndex]; + } + + const messages = await Message.findAll({ + where: { ticketId: ticket.id }, + order: [["createdAt", "ASC"]], + limit: prompt.maxMessages + }); + + const promptSystem = `Nas respostas utilize o nome ${sanitizeName( + contact.name || "Amigo(a)" + )} para identificar o cliente.\nSua resposta deve usar no máximo ${prompt.maxTokens + } tokens e cuide para não truncar o final.\nSempre que possível, mencione o nome dele para ser mais personalizado o atendimento e mais educado. Quando a resposta requer uma transferência para o setor de atendimento, comece sua resposta com 'Ação: Transferir para o setor de atendimento'.\n + ${prompt.prompt}\n`; + + let messagesOpenAi: ChatCompletionRequestMessage[] = []; + + if (msg.message?.conversation || msg.message?.extendedTextMessage?.text) { + messagesOpenAi = []; + messagesOpenAi.push({ role: "system", content: promptSystem }); + for ( + let i = 0; + i < Math.min(prompt.maxMessages, messages.length); + i++ + ) { + const message = messages[i]; + if (message.mediaType === "chat") { + if (message.fromMe) { + messagesOpenAi.push({ role: "assistant", content: message.body }); + } else { + messagesOpenAi.push({ role: "user", content: message.body }); + } + } + } + messagesOpenAi.push({ role: "user", content: bodyMessage! }); + + const chat = await openai.createChatCompletion({ + model: "gpt-3.5-turbo-1106", + messages: messagesOpenAi, + max_tokens: prompt.maxTokens, + temperature: prompt.temperature + }); + + let response = chat.data.choices[0].message?.content; + + if (response?.includes("Ação: Transferir para o setor de atendimento")) { + await transferQueue(prompt.queueId, ticket, contact); + response = response + .replace("Ação: Transferir para o setor de atendimento", "") + .trim(); + } + + if (prompt.voice === "texto") { + const sentMessage = await wbot.sendMessage(msg.key.remoteJid!, { + text: response! + }); + await verifyMessage(sentMessage!, ticket, contact); + } else { + const fileNameWithOutExtension = `${ticket.id}_${Date.now()}`; + convertTextToSpeechAndSaveToFile( + keepOnlySpecifiedChars(response!), + `${publicFolder}/${fileNameWithOutExtension}`, + prompt.voiceKey, + prompt.voiceRegion, + prompt.voice, + "mp3" + ).then(async () => { + try { + const sendMessage = await wbot.sendMessage(msg.key.remoteJid!, { + audio: { url: `${publicFolder}/${fileNameWithOutExtension}.mp3` }, + mimetype: "audio/mpeg", + ptt: true + }); + await verifyMediaMessage(sendMessage!, ticket, contact); + deleteFileSync(`${publicFolder}/${fileNameWithOutExtension}.mp3`); + deleteFileSync(`${publicFolder}/${fileNameWithOutExtension}.wav`); + } catch (error) { + console.log(`Erro para responder com audio: ${error}`); + } + }); + } + } else if (msg.message?.audioMessage) { + const mediaUrl = mediaSent!.mediaUrl!.split("/").pop(); + const file = fs.createReadStream(`${publicFolder}/${mediaUrl}`) as any; + const transcription = await openai.createTranscription(file, "whisper-1"); + + messagesOpenAi = []; + messagesOpenAi.push({ role: "system", content: promptSystem }); + for ( + let i = 0; + i < Math.min(prompt.maxMessages, messages.length); + i++ + ) { + const message = messages[i]; + if (message.mediaType === "chat") { + if (message.fromMe) { + messagesOpenAi.push({ role: "assistant", content: message.body }); + } else { + messagesOpenAi.push({ role: "user", content: message.body }); + } + } + } + messagesOpenAi.push({ role: "user", content: transcription.data.text }); + const chat = await openai.createChatCompletion({ + model: "gpt-3.5-turbo-1106", + messages: messagesOpenAi, + max_tokens: prompt.maxTokens, + temperature: prompt.temperature + }); + let response = chat.data.choices[0].message?.content; + + if (response?.includes("Ação: Transferir para o setor de atendimento")) { + await transferQueue(prompt.queueId, ticket, contact); + response = response + .replace("Ação: Transferir para o setor de atendimento", "") + .trim(); + } + if (prompt.voice === "texto") { + const sentMessage = await wbot.sendMessage(msg.key.remoteJid!, { + text: response! + }); + await verifyMessage(sentMessage!, ticket, contact); + } else { + const fileNameWithOutExtension = `${ticket.id}_${Date.now()}`; + convertTextToSpeechAndSaveToFile( + keepOnlySpecifiedChars(response!), + `${publicFolder}/${fileNameWithOutExtension}`, + prompt.voiceKey, + prompt.voiceRegion, + prompt.voice, + "mp3" + ).then(async () => { + try { + const sendMessage = await wbot.sendMessage(msg.key.remoteJid!, { + audio: { url: `${publicFolder}/${fileNameWithOutExtension}.mp3` }, + mimetype: "audio/mpeg", + ptt: true + }); + await verifyMediaMessage(sendMessage!, ticket, contact); + deleteFileSync(`${publicFolder}/${fileNameWithOutExtension}.mp3`); + deleteFileSync(`${publicFolder}/${fileNameWithOutExtension}.wav`); + } catch (error) { + console.log(`Erro para responder com audio: ${error}`); + } + }); + } + } + messagesOpenAi = []; +}; + + +const transferQueue = async ( + queueId: number, + ticket: Ticket, + contact: Contact +): Promise => { + await UpdateTicketService({ + ticketData: { queueId: queueId, useIntegration: false, promptId: null }, + ticketId: ticket.id, + companyId: ticket.companyId + }); +}; + + +const verifyMediaMessage = async ( + msg: proto.IWebMessageInfo, + ticket: Ticket, + contact: Contact +): Promise => { + const io = getIO(); + const quotedMsg = await verifyQuotedMessage(msg); + const media = await downloadMedia(msg); + + if (!media) { + throw new Error("ERR_WAPP_DOWNLOAD_MEDIA"); + } + + if (!media.filename) { + const ext = media.mimetype.split("/")[1].split(";")[0]; + media.filename = `${new Date().getTime()}.${ext}`; + } + + try { + + const folder = `public/company${ticket.companyId}`; + if (!fs.existsSync(folder)) { + fs.mkdirSync(folder); + fs.chmodSync(folder, 0o777) + } + + await writeFileAsync( + join(__dirname, "..", "..", "..", folder, media.filename), + media.data, + "base64" + ); + + await new Promise((resolve, reject) => { + if (media.filename.includes('.ogg')) { + ffmpeg(folder + '/' + media.filename) + .toFormat('mp3') + .save((folder + '/' + media.filename).replace('.ogg', '.mp3')) + .on('end', () => { + logger.info('Conversão concluída!'); + resolve(); + }) + .on('error', (err) => { + logger.error('Erro durante a conversão:', err); + reject(err); + }); + } else { + logger.info('Não é necessário converter o arquivo. Não é formato OGG.'); + resolve(); // Resolve immediately since no conversion is needed. + } + }); + + + } catch (err) { + Sentry.captureException(err); + logger.error(err); + } + + const body = getBodyMessage(msg); + + + const messageData = { + id: msg.key.id, + ticketId: ticket.id, + contactId: msg.key.fromMe ? undefined : contact.id, + body: body ? formatBody(body, ticket.contact) : media.filename, + fromMe: msg.key.fromMe, + read: msg.key.fromMe, + mediaUrl: media.filename, + mediaType: media.mimetype.split("/")[0], + quotedMsgId: quotedMsg?.id, + ack: msg.status, + remoteJid: msg.key.remoteJid, + participant: msg.key.participant, + dataJson: JSON.stringify(msg), + }; + + await ticket.update({ + lastMessage: body || media.filename, + }); + + const newMessage = await CreateMessageService({ + messageData, + companyId: ticket.companyId, + }); + + + if (!msg.key.fromMe && ticket.status === "closed") { + await ticket.update({ status: "pending" }); + await ticket.reload({ + include: [ + { model: Queue, as: "queue" }, + { model: User, as: "user" }, + { model: Contact, as: "contact" }, + ], + }); + + io.to(`company-${ticket.companyId}-closed`) + .to(`queue-${ticket.queueId}-closed`) + .emit(`company-${ticket.companyId}-ticket`, { + action: "delete", + ticket, + ticketId: ticket.id, + }); + + io.to(`company-${ticket.companyId}-${ticket.status}`) + .to(`queue-${ticket.queueId}-${ticket.status}`) + .to(ticket.id.toString()) + .emit(`company-${ticket.companyId}-ticket`, { + action: "update", + ticket, + ticketId: ticket.id, + }); + } + + return newMessage; +}; + +function getStatus(msg, msgType) { + + if (msg.status == "PENDING") { + + if (msg.key.fromMe && msgType == "reactionMessage"){ + return 3; + } + + return 1 + } else if (msg.status == "SERVER_ACK") { + return 1 + } + return msg.status; +} + + +export const verifyMessage = async ( + msg: proto.IWebMessageInfo, + ticket: Ticket, + contact: Contact +) => { + const io = getIO(); + const quotedMsg = await verifyQuotedMessage(msg); + const body = getBodyMessage(msg); + const isEdited = getTypeMessage(msg) == 'editedMessage'; + + const messageData = { + id: isEdited ? msg?.message?.editedMessage?.message?.protocolMessage?.key?.id : msg.key.id, + ticketId: ticket.id, + contactId: msg.key.fromMe ? undefined : contact.id, + body, + fromMe: msg.key.fromMe, + mediaType: getTypeMessage(msg), + read: msg.key.fromMe, + quotedMsgId: quotedMsg?.id, + ack: msg.status, + remoteJid: msg.key.remoteJid, + participant: msg.key.participant, + dataJson: JSON.stringify(msg), + isEdited: isEdited, + }; + + await ticket.update({ + lastMessage: body + }); + + + await CreateMessageService({ messageData, companyId: ticket.companyId }); + + if (!msg.key.fromMe && ticket.status === "closed") { + await ticket.update({ status: "pending" }); + await ticket.reload({ + include: [ + { model: Queue, as: "queue" }, + { model: User, as: "user" }, + { model: Contact, as: "contact" } + ] + }); + + io.to(`company-${ticket.companyId}-closed`) + .to(`queue-${ticket.queueId}-closed`) + .emit(`company-${ticket.companyId}-ticket`, { + action: "delete", + ticket, + ticketId: ticket.id + }); + + io.to(`company-${ticket.companyId}-${ticket.status}`) + .to(`queue-${ticket.queueId}-${ticket.status}`) + .emit(`company-${ticket.companyId}-ticket`, { + action: "update", + ticket, + ticketId: ticket.id + }); + } +}; + +const isValidMsg = (msg: proto.IWebMessageInfo): boolean => { + if (msg.key.remoteJid === "status@broadcast") return false; + try { + const msgType = getTypeMessage(msg); + if (!msgType) { + return; + } + + const ifType = + msgType === "conversation" || + msgType === "extendedTextMessage" || + msgType === "editedMessage" || + msgType === "audioMessage" || + msgType === "videoMessage" || + msgType === "imageMessage" || + msgType === "documentMessage" || + msgType === "documentWithCaptionMessage" || + msgType === "stickerMessage" || + msgType === "buttonsResponseMessage" || + msgType === "buttonsMessage" || + msgType === "messageContextInfo" || + msgType === "locationMessage" || + msgType === "liveLocationMessage" || + msgType === "contactMessage" || + msgType === "voiceMessage" || + msgType === "mediaMessage" || + msgType === "contactsArrayMessage" || + msgType === "reactionMessage" || + msgType === "ephemeralMessage" || + msgType === "protocolMessage" || + msgType === "listResponseMessage" || + msgType === "listMessage" || + msgType === "viewOnceMessage"; + + if (!ifType) { + logger.warn(`#### Nao achou o type em isValidMsg: ${msgType} +${JSON.stringify(msg?.message)}`); + Sentry.setExtra("Mensagem", { BodyMsg: msg.message, msg, msgType }); + Sentry.captureException(new Error("Novo Tipo de Mensagem em isValidMsg")); + } + + return !!ifType; + } catch (error) { + Sentry.setExtra("Error isValidMsg", { msg }); + Sentry.captureException(error); + } +}; + + +const Push = (msg: proto.IWebMessageInfo) => { + return msg.pushName; +} +const verifyQueue = async ( + wbot: Session, + msg: proto.IWebMessageInfo, + ticket: Ticket, + contact: Contact, + mediaSent?: Message | undefined +) => { + const companyId = ticket.companyId; + + const { queues, greetingMessage, maxUseBotQueues, timeUseBotQueues } = await ShowWhatsAppService( + wbot.id!, + ticket.companyId + ) + + if (queues.length === 1) { + + const sendGreetingMessageOneQueues = await Setting.findOne({ + where: { + key: "sendGreetingMessageOneQueues", + companyId: ticket.companyId + } + }); + + if (greetingMessage.length > 1 && sendGreetingMessageOneQueues?.value === "enabled") { + const body = formatBody(`${greetingMessage}`, contact); + + console.log('body2', body) + await wbot.sendMessage( + `${contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + { + text: body + } + ); + } + + const firstQueue = head(queues); + let chatbot = false; + if (firstQueue?.options) { + chatbot = firstQueue.options.length > 0; + } + + + //inicia integração dialogflow/n8n + if ( + !msg.key.fromMe && + !ticket.isGroup && + !isNil(queues[0]?.integrationId) + ) { + const integrations = await ShowQueueIntegrationService(queues[0].integrationId, companyId); + + await handleMessageIntegration(msg, wbot, integrations, ticket) + + await ticket.update({ + useIntegration: true, + integrationId: integrations.id + }) + // return; + } + //inicia integração openai + if ( + !msg.key.fromMe && + !ticket.isGroup && + !isNil(queues[0]?.promptId) + ) { + + + + await handleOpenAi(msg, wbot, ticket, contact, mediaSent); + + + await ticket.update({ + useIntegration: true, + promptId: queues[0]?.promptId + }) + // return; + } + + await UpdateTicketService({ + ticketData: { queueId: firstQueue.id, chatbot, status: "pending" }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + + return; + } + + const lastMessage = await Message.findOne({ + where: { + ticketId: ticket.id, + fromMe: true + }, + order: [["createdAt", "DESC"]] + }); + + + // REGRA PARA DESABILITAR O BOT PARA ALGUM CONTATO + if (contact.disableBot) { + return; + } + + const selectedOption = getBodyMessage(msg); + + const choosenQueue = /\*\[\s*\d+\s*\]\*\s*-\s*.*/g.test(lastMessage?.body) + ? queues[+selectedOption - 1] + : undefined; + + + const buttonActive = await Setting.findOne({ + where: { + key: "chatBotType", + companyId + } + }); + + + + /** + * recebe as mensagens dos usuários e envia as opções de fila + * tratamento de mensagens para resposta aos usuarios apartir do chatbot/fila. + */ + const botText = async () => { + let options = ""; + + queues.forEach((queue, index) => { + options += `*[ ${index + 1} ]* - ${queue.name}\n`; + }); + + + const textMessage = { + text: formatBody(`\u200e${greetingMessage}\n\n${options}`, contact), + }; + let lastMsg = map_msg.get(contact.number) + let invalidOption = "Opção inválida, por favor, escolha uma opção válida." + + + // console.log('getBodyMessage(msg)', getBodyMessage(msg)) + console.log('textMessage2', textMessage) + console.log("lastMsg::::::::::::':", contact.number) + // map_msg.set(contact.number, lastMsg); + if (!lastMsg?.msg || getBodyMessage(msg).includes('#') || textMessage.text === 'concluido' || lastMsg.msg !== textMessage.text && !lastMsg.invalid_option) { + const sendMsg = await wbot.sendMessage( + `${contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + textMessage + ); + lastMsg ?? (lastMsg = {}); + lastMsg.msg = textMessage.text; + lastMsg.invalid_option = false; + map_msg.set(contact.number, lastMsg); + await verifyMessage(sendMsg, ticket, ticket.contact); + + } else if (lastMsg.msg !== invalidOption && !lastMsg.invalid_option) { + textMessage.text = invalidOption + const sendMsg = await wbot.sendMessage( + `${contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + textMessage + ); + lastMsg ?? (lastMsg = {}); + lastMsg.invalid_option = true; + lastMsg.msg = textMessage.text; + map_msg.set(contact.number, lastMsg); + await verifyMessage(sendMsg, ticket, ticket.contact); + } + + }; + + if (choosenQueue) { + let chatbot = false; + if (choosenQueue?.options) { + chatbot = choosenQueue.options.length > 0; + } + + await UpdateTicketService({ + ticketData: { queueId: choosenQueue.id, chatbot }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + + +/* Tratamento para envio de mensagem quando a fila está fora do expediente */ +if (choosenQueue.options.length === 0) { + const queue = await Queue.findByPk(choosenQueue.id); + const { schedules }: any = queue; + const now = moment(); + const weekday = now.format("dddd").toLowerCase(); + let schedule; + + if (Array.isArray(schedules) && schedules.length > 0) { + schedule = schedules.find((s) => s.weekdayEn === weekday && s.startTimeA !== "" && s.startTimeA !== null && s.endTimeB !== "" && s.endTimeB !== null); + } + + if (queue.outOfHoursMessage !== null && queue.outOfHoursMessage !== "" && !isNil(schedule)) { + const startTimeA = moment(schedule.startTimeA, "HH:mm"); + const endTimeA = moment(schedule.endTimeA, "HH:mm"); + const startTimeB = schedule.startTimeB ? moment(schedule.startTimeB, "HH:mm") : null; + const endTimeB = schedule.endTimeB ? moment(schedule.endTimeB, "HH:mm") : null; + + const isWithinBusinessHours = (now.isBetween(startTimeA, endTimeA, null, '[]') || (startTimeB && endTimeB && now.isBetween(startTimeB, endTimeB, null, '[]'))); + + if (!isWithinBusinessHours) { + // Verifica se o status do ticket é "open" ou "pendent" ou "assigned" + if (ticket.status === "open" || ticket.status === "pendent" || ticket.status === "assigned") { + // Envia a mensagem de fora do expediente + const body = formatBody(`\u200e${queue.outOfHoursMessage}`, ticket.contact); + console.log('body222', body); + + // Envia a mensagem + const sentMessage = await wbot.sendMessage( + `${contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, { + text: body, + }); + + // Verifica a mensagem + await verifyMessage(sentMessage, ticket, contact); + + // Finaliza o ticket com o status 'closed' + await UpdateTicketService({ + ticketData: { status: "closed", queueId: null, chatbot }, + ticketId: ticket.id, + companyId: ticket.companyId, + }); + + // Envia a mensagem de finalização + const finalizationMessage = "Seu ticket foi finalizado porque estamos *Offline* no momento."; + await wbot.sendMessage( + `${contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, { + text: finalizationMessage, + }); + } + } else if (ticket.status === "assigned") { + // Prevent looping by checking if the ticket is assigned + console.log("Ticket is assigned, no need to send out-of-hours message."); + return; // Skip further processing if assigned + } + } + + + + + + //inicia integração dialogflow/n8n + if ( + !msg.key.fromMe && + !ticket.isGroup && + choosenQueue.integrationId + ) { + const integrations = await ShowQueueIntegrationService(choosenQueue.integrationId, companyId); + + await handleMessageIntegration(msg, wbot, integrations, ticket) + + await ticket.update({ + useIntegration: true, + integrationId: integrations.id + }) + // return; + } + + //inicia integração openai + if ( + !msg.key.fromMe && + !ticket.isGroup && + !isNil(choosenQueue?.promptId) + ) { + await handleOpenAi(msg, wbot, ticket, contact, mediaSent); + + + await ticket.update({ + useIntegration: true, + promptId: choosenQueue?.promptId + }) + // return; + } + + const body = formatBody(`\u200e${choosenQueue.greetingMessage}`, ticket.contact + ); + if (choosenQueue.greetingMessage) { + console.log('Chegou em wbotMessageListener.ts:', body) + const sentMessage = await wbot.sendMessage( + `${contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, { + text: body, + } + ); + await verifyMessage(sentMessage, ticket, contact); + } + /*if (choosenQueue.mediaPath !== null && choosenQueue.mediaPath !== "") { + const filePath = path.resolve("public", choosenQueue.mediaPath); + + const optionsMsg = await getMessageOptions(choosenQueue.mediaName, filePath); + + let sentMessage = await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, { ...optionsMsg }); + + await verifyMediaMessage(sentMessage, ticket, contact); + }*/ + + if (choosenQueue.mediaPath !== null && choosenQueue.mediaPath !== "") { + const companyId = ticket.companyId.toString(); + const fileName = choosenQueue.mediaPath; // Usar mediaPath como nome do arquivo + const filePath = path.resolve("public", `company${companyId}`, fileName); + const optionsMsg = await getMessageOptions(fileName, filePath, companyId); + let sentMessage = await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, { ...optionsMsg }); + await verifyMediaMessage(sentMessage, ticket, contact); + } + } + + } else { + + if (maxUseBotQueues && maxUseBotQueues !== 0 && ticket.amountUsedBotQueues >= maxUseBotQueues) { + // await UpdateTicketService({ + // ticketData: { queueId: queues[0].id }, + // ticketId: ticket.id + // }); + + return; + } + + //Regra para desabilitar o chatbot por x minutos/horas após o primeiro envio + const ticketTraking = await FindOrCreateATicketTrakingService({ ticketId: ticket.id, companyId }); + let dataLimite = new Date(); + let Agora = new Date(); + + + if (ticketTraking.chatbotAt !== null) { + dataLimite.setMinutes(ticketTraking.chatbotAt.getMinutes() + (Number(timeUseBotQueues))); + + if (ticketTraking.chatbotAt !== null && Agora < dataLimite && timeUseBotQueues !== "0" && ticket.amountUsedBotQueues !== 0) { + return + } + } + await ticketTraking.update({ + chatbotAt: null + }) + + if (buttonActive.value === "text") { + return botText(); + } + + } + +}; + + +export const verifyRating = (ticketTraking: TicketTraking) => { + if ( + ticketTraking && + ticketTraking.finishedAt === null && + ticketTraking.userId !== null && + ticketTraking.ratingAt !== null + ) { + return true; + } + return false; +}; + +export const handleRating = async ( + rate: number, + ticket: Ticket, + ticketTraking: TicketTraking, + contact: Contact +) => { + const io = getIO(); + + const { complationMessage } = await ShowWhatsAppService( + ticket.whatsappId, + ticket.companyId + ); + + let finalRate = rate; + + if (rate < 1) { + finalRate = 1; + } + if (rate > 5) { + finalRate = 5; + } + + await UserRating.create({ + ticketId: ticketTraking.ticketId, + companyId: ticketTraking.companyId, + userId: ticketTraking.userId, + rate: finalRate, + }); + + if (complationMessage) { + const body = formatBody(`\u200e${complationMessage}`, ticket.contact); + const msg = await SendWhatsAppMessage({ body, ticket }); + await verifyMessage(msg, ticket, contact); + } + + await ticketTraking.update({ + finishedAt: moment().toDate(), + rated: true, + }); + + // Manter a fila no ticket ao fechá-lo + await ticket.update({ + // Remover esses campos, já que queremos manter a fila + queueOptionId: null, + userId: null, + status: "closed", + // Não removemos queueId, pois a fila deve ser mantida + }); + + io.to(`company-${ticket.companyId}-open`) + .to(`queue-${ticket.queueId}-open`) + .emit(`company-${ticket.companyId}-ticket`, { + action: "delete", + ticket, + ticketId: ticket.id, + }); + + io.to(`company-${ticket.companyId}-${ticket.status}`) + .to(`queue-${ticket.queueId}-${ticket.status}`) + .to(ticket.id.toString()) + .emit(`company-${ticket.companyId}-ticket`, { + action: "update", + ticket, + ticketId: ticket.id, + }); +}; + + +const handleChartbot = async (ticket: Ticket, msg: WAMessage, wbot: Session, dontReadTheFirstQuestion = false) => { + const queue = await Queue.findByPk(ticket.queueId, { + include: [ + { + model: QueueOption, + as: "options", + where: { parentId: null }, + }, + ], + order: [ + ["options", "option", "ASC"], + ] + }); + + + + const messageBody = getBodyMessage(msg); + + + if (messageBody == "#") { + // voltar para o menu inicial + await ticket.update({ queueOptionId: null, chatbot: false, queueId: null }); + await verifyQueue(wbot, msg, ticket, ticket.contact); + return; + } + + // voltar para o menu anterior + if (!isNil(queue) && !isNil(ticket.queueOptionId) && messageBody == "0") { + const option = await QueueOption.findByPk(ticket.queueOptionId); + await ticket.update({ queueOptionId: option?.parentId }); + + // escolheu uma opção + } else if (!isNil(queue) && !isNil(ticket.queueOptionId)) { + + + const count = await QueueOption.count({ + where: { parentId: ticket.queueOptionId }, + }); + let option: any = {}; + if (count == 1) { + option = await QueueOption.findOne({ + where: { parentId: ticket.queueOptionId }, + }); + } else { + option = await QueueOption.findOne({ + where: { + option: messageBody || "", + parentId: ticket.queueOptionId, + }, + }); + } + if (option) { + await ticket.update({ queueOptionId: option?.id }); + } + + // não linha a primeira pergunta + } else if (!isNil(queue) && isNil(ticket.queueOptionId) && !dontReadTheFirstQuestion) { + const option = queue?.options.find((o) => o.option == messageBody); + if (option) { + await ticket.update({ queueOptionId: option?.id }); + } + } + + await ticket.reload(); + + if (!isNil(queue) && isNil(ticket.queueOptionId)) { + + + const queueOptions = await QueueOption.findAll({ + where: { queueId: ticket.queueId, parentId: null }, + order: [ + ["option", "ASC"], + ["createdAt", "ASC"], + ], + }); + + const companyId = ticket.companyId; + + const buttonActive = await Setting.findOne({ + where: { + key: "chatBotType", + companyId + } + }); + + // const botList = async () => { + // const sectionsRows = []; + + // queues.forEach((queue, index) => { + // sectionsRows.push({ + // title: queue.name, + // rowId: `${index + 1}` + // }); + // }); + + // const sections = [ + // { + // rows: sectionsRows + // } + // ]; + + + // const listMessage = { + // text: formatBody(`\u200e${queue.greetingMessage}`, ticket.contact), + // buttonText: "Escolha uma opção", + // sections + // }; + + // const sendMsg = await wbot.sendMessage( + // `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + // listMessage + // ); + + // await verifyMessage(sendMsg, ticket, ticket.contact); + // } + + const botButton = async () => { + const buttons = []; + queueOptions.forEach((option, i) => { + buttons.push({ + buttonId: `${option.option}`, + buttonText: { displayText: option.title }, + type: 4 + }); + }); + buttons.push({ + buttonId: `#`, + buttonText: { displayText: "Menu inicial *[ 0 ]* Menu anterior" }, + type: 4 + }); + + const buttonMessage = { + text: formatBody(`\u200e${queue.greetingMessage}`, ticket.contact), + buttons, + headerType: 4 + }; + + const sendMsg = await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + buttonMessage + ); + + await verifyMessage(sendMsg, ticket, ticket.contact); + } + + const botText = async () => { + let options = ""; + + queueOptions.forEach((option, i) => { + options += `*[ ${option.option} ]* - ${option.title}\n`; + }); + //options += `\n*[ 0 ]* - Menu anterior`; + options += `\n*[ # ]* - Menu inicial`; + + const textMessage = { + text: formatBody(`\u200e${queue.greetingMessage}\n\n${options}`, ticket.contact), + }; + + console.log('textMessage5555555555555', textMessage) + const sendMsg = await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + textMessage + ); + + await verifyMessage(sendMsg, ticket, ticket.contact); + }; + + // if (buttonActive.value === "list") { + // return botList(); + // }; + + if (buttonActive.value === "button" && QueueOption.length <= 4) { + return botButton(); + } + + if (buttonActive.value === "text") { + return botText(); + } + + if (buttonActive.value === "button" && QueueOption.length > 4) { + return botText(); + } + } else if (!isNil(queue) && !isNil(ticket.queueOptionId)) { + const currentOption = await QueueOption.findByPk(ticket.queueOptionId); + const queueOptions = await QueueOption.findAll({ + where: { parentId: ticket.queueOptionId }, + order: [ + ["option", "ASC"], + ["createdAt", "ASC"], + ], + }); + + if (queueOptions.length === 0) { + const textMessage = { + text: formatBody(`\u200e${currentOption.message}`, ticket.contact), + }; + + const sendMsg = await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + textMessage + ); + + await verifyMessage(sendMsg, ticket, ticket.contact); + if (currentOption.mediaPath !== null && currentOption.mediaPath !== "") { + + const filePath = path.resolve("public", currentOption.mediaPath); + + + const optionsMsg = await getMessageOptions(currentOption.mediaName, filePath); + + let sentMessage = await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, { ...optionsMsg }); + + await verifyMediaMessage(sentMessage, ticket, ticket.contact); + } + + await verifyMessage(sendMsg, ticket, ticket.contact); + + await ticket.update({ + queueOptionId: null, + chatbot: false, + }); + //console.log("Fim do chatbot. Última opção alcançada."); + return; + } + + if (queueOptions.length > -1) { + + const companyId = ticket.companyId; + const buttonActive = await Setting.findOne({ + where: { + key: "chatBotType", + companyId + } + }); + + const botList = async () => { + const sectionsRows = []; + + queueOptions.forEach((option, i) => { + sectionsRows.push({ + title: option.title, + rowId: `${option.option}` + }); + }); + sectionsRows.push({ + title: "Menu inicial *[ 0 ]* Menu anterior", + rowId: `#` + }); + const sections = [ + { + rows: sectionsRows + } + ]; + + const listMessage = { + text: formatBody(`\u200e${currentOption.message}`, ticket.contact), + buttonText: "Escolha uma opção", + sections + }; + + const sendMsg = await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + listMessage + ); + + await verifyMessage(sendMsg, ticket, ticket.contact); + } + + const botButton = async () => { + const buttons = []; + queueOptions.forEach((option, i) => { + buttons.push({ + buttonId: `${option.option}`, + buttonText: { displayText: option.title }, + type: 4 + }); + }); + buttons.push({ + buttonId: `#`, + buttonText: { displayText: "Menu inicial *[ 0 ]* Menu anterior" }, + type: 4 + }); + + const buttonMessage = { + text: formatBody(`\u200e${currentOption.message}`, ticket.contact), + buttons, + headerType: 4 + }; + + const sendMsg = await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + buttonMessage + ); + + await verifyMessage(sendMsg, ticket, ticket.contact); + } + + const botText = async () => { + + let options = ""; + + queueOptions.forEach((option, i) => { + options += `*[ ${option.option} ]* - ${option.title}\n`; + }); + options += `\n*[ 0 ]* - Menu anterior`; + options += `\n*[ # ]* - Menu inicial`; + const textMessage = { + text: formatBody(`\u200e${currentOption.message}\n\n${options}`, ticket.contact), + }; + + console.log('textMessage6666666666', textMessage) + const sendMsg = await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, + textMessage + ); + + await verifyMessage(sendMsg, ticket, ticket.contact); + if (currentOption.mediaPath !== null && currentOption.mediaPath !== "") { + + const filePath = path.resolve("public", currentOption.mediaPath); + + + const optionsMsg = await getMessageOptions(currentOption.mediaName, filePath); + + let sentMessage = await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net"}`, { ...optionsMsg }); + + await verifyMediaMessage(sentMessage, ticket, ticket.contact); + } + }; + + if (buttonActive.value === "list") { + return botList(); + }; + + if (buttonActive.value === "button" && QueueOption.length <= 4) { + return botButton(); + } + + if (buttonActive.value === "text") { + return botText(); + } + + if (buttonActive.value === "button" && QueueOption.length > 4) { + return botText(); + } + } + } +} + +export const handleMessageIntegration = async ( + msg: proto.IWebMessageInfo, + wbot: Session, + queueIntegration: QueueIntegrations, + ticket: Ticket +): Promise => { + const msgType = getTypeMessage(msg); + + if (queueIntegration.type === "n8n" || queueIntegration.type === "webhook") { + if (queueIntegration?.urlN8N) { + const options = { + method: "POST", + url: queueIntegration?.urlN8N, + headers: { + "Content-Type": "application/json" + }, + json: msg + }; + try { + request(options, function (error, response) { + if (error) { + throw new Error(error); + } + else { + console.log(response.body); + } + }); + } catch (error) { + throw new Error(error); + } + } + + } else if (queueIntegration.type === "typebot") { + console.log("entrou no typebot") + // await typebots(ticket, msg, wbot, queueIntegration); + await typebotListener({ ticket, msg, wbot, typebot: queueIntegration }); + + } +} + +const handleMessage = async ( + msg: proto.IWebMessageInfo, + wbot: Session, + companyId: number +): Promise => { + let mediaSent: Message | undefined; + + if (!isValidMsg(msg)) return; + try { + let msgContact: IMe; + let groupContact: Contact | undefined; + + const isGroup = msg.key.remoteJid?.endsWith("@g.us"); + + const msgIsGroupBlock = await Setting.findOne({ + where: { + companyId, + key: "CheckMsgIsGroup" + } + }); + + const bodyMessage = getBodyMessage(msg); + + // Verifica se a mensagem é "#assumir" e foi enviada pelo atendente + /*if (msg.key.fromMe && bodyMessage === "#assumir") { + console.log("Comando #assumir detectado!"); + // Vamos adicionar mais lógica aqui nos próximos passos + return; // Para evitar que o resto da função processe essa mensagem + }*/ + + + const msgType = getTypeMessage(msg); + + const hasMedia = + msg.message?.audioMessage || + msg.message?.imageMessage || + msg.message?.videoMessage || + msg.message?.documentMessage || + msg.message?.documentWithCaptionMessage || + msg.message.stickerMessage; + if (msg.key.fromMe) { + if (/\u200e/.test(bodyMessage)) return; + + if ( + !hasMedia && + msgType !== "conversation" && + msgType !== "extendedTextMessage" && + msgType !== "vcard" + ) + return; + } + + msgContact = await getContactMessage(msg, wbot); + + if (msgIsGroupBlock?.value === "enabled" && isGroup) return; + + if (isGroup) { + groupContact = await wbotMutex.runExclusive(async () => { + let result = groupContactCache.get(msg.key.remoteJid); + if (!result) { + const groupMetadata = await wbot.groupMetadata(msg.key.remoteJid); + const msgGroupContact = { + id: groupMetadata.id, + name: groupMetadata.subject, + } + result = await verifyContact(msgGroupContact, wbot, companyId); + groupContactCache.set(msg.key.remoteJid, result); + } + return result; + }); + } + + const whatsapp = await ShowWhatsAppService(wbot.id!, companyId); + const contact = await verifyContact(msgContact, wbot, companyId); + + let unreadMessages = 0; + + + if (msg.key.fromMe) { + await cacheLayer.set(`contacts:${contact.id}:unreads`, "0"); + } else { + const unreads = await cacheLayer.get(`contacts:${contact.id}:unreads`); + unreadMessages = +unreads + 1; + await cacheLayer.set( + `contacts:${contact.id}:unreads`, + `${unreadMessages}` + ); + } + + const lastMessage = await Message.findOne({ + where: { + contactId: contact.id, + companyId, + }, + order: [["createdAt", "DESC"]], + }); + + + if (unreadMessages === 0 && whatsapp.complationMessage && formatBody(whatsapp.complationMessage, contact).trim().toLowerCase() === lastMessage?.body.trim().toLowerCase()) { + return; + } + + + const ticket = await FindOrCreateTicketService(contact, wbot.id!, unreadMessages, companyId, groupContact); + + + // Verifica se a mensagem é "#assumir" e foi enviada pelo atendente +if (msg.key.fromMe && bodyMessage === "#assumir") { + console.log("Comando #assumir detectado!"); + + // Busca o ticket já criado anteriormente na função + const ticket = await FindOrCreateTicketService(contact, wbot.id!, unreadMessages, companyId, groupContact); + + // Verifica se o ticket está no status "pending" + if (ticket.status === "pending") { + console.log(`Ticket ${ticket.id} está no status 'pending'. Pronto para ser assumido.`); + + // Pega o número da empresa conectado ao wbot + const whatsapp = await ShowWhatsAppService(wbot.id!, companyId); + const companyNumber = whatsapp.number; // Número da empresa conectado ao Whaticket + console.log(`Número da empresa conectado: ${companyNumber}`); + + // Busca o atendente associado ao número da empresa + const attendant = await User.findOne({ + where: { + whatsappNumber: companyNumber // O número da empresa deve estar no whatsappNumber do atendente + } + }); + + if (attendant) { + // Se o atendente foi encontrado, atualiza o ticket + await ticket.update({ + status: "open", + userId: attendant.id, + chatbot: false + }); + console.log(`Ticket ${ticket.id} atualizado para 'open'. Atendente ${attendant.id} assumiu a conversa.`); + } else { + console.log(`Nenhum atendente encontrado com o número ${companyNumber}. O ticket não foi assumido.`); + } + } else { + console.log(`Ticket ${ticket.id} não está no status 'pending'. Status atual: ${ticket.status}`); + } + + return; // Para evitar que o resto da função processe essa mensagem +} + + + + await provider(ticket, msg, companyId, contact, wbot as WASocket); + + + const ticketTraking = await FindOrCreateATicketTrakingService({ + ticketId: ticket.id, + companyId, + whatsappId: whatsapp?.id + }); + + + try { + if (!msg.key.fromMe && !contact.isGroup) { + + if ( + ticketTraking !== null && + isNumeric(bodyMessage) && + verifyRating(ticketTraking) + ) { + await handleRating( + parseFloat(bodyMessage), + ticket, + ticketTraking, + contact + ); + return; + } + } + } catch (e) { + Sentry.captureException(e); + console.log(e); + } + + + // Atualiza o ticket se a ultima mensagem foi enviada por mim, para que possa ser finalizado. + try { + await ticket.update({ + fromMe: msg.key.fromMe, + }); + } catch (e) { + Sentry.captureException(e); + console.log(e); + } + + if (hasMedia) { + mediaSent = await verifyMediaMessage(msg, ticket, contact); + } else { + await verifyMessage(msg, ticket, contact); + } + + if (isGroup || contact.disableBot) { + return; + } + + const currentSchedule = await VerifyCurrentSchedule(companyId); + const scheduleType = await Setting.findOne({ + where: { + companyId, + key: "scheduleType" + } + }); + + + try { + if (!msg.key.fromMe && scheduleType) { + /** + * Tratamento para envio de mensagem quando a empresa está fora do expediente + */ + if ( + scheduleType.value === "company" && + !isNil(currentSchedule) && + (!currentSchedule || currentSchedule.inActivity === false) + ) { + const body = `\u200e ${whatsapp.outOfHoursMessage}`; + + console.log('body9341023', body) + const debouncedSentMessage = debounce( + async () => { + await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net" + }`, + { + text: body + } + ); + }, + 3000, + ticket.id + ); + debouncedSentMessage(); + return; + } + + console.log('MSG:', bodyMessage); + if (scheduleType.value === "queue" && ticket.queueId !== null) { + + /** + * Tratamento para envio de mensagem quando a fila está fora do expediente + */ + + + const queue = await Queue.findByPk(ticket.queueId); + + const { schedules }: any = queue; + const now = moment(); + const weekday = now.format("dddd").toLowerCase(); + let schedule = null; + + if (Array.isArray(schedules) && schedules.length > 0) { + schedule = schedules.find( + s => + s.weekdayEn === weekday && + s.startTimeA !== "" && + s.startTimeA !== null && + s.endTimeA !== "" && + s.endTimeA !== null + ); + } + + if ( + scheduleType.value === "queue" && + queue.outOfHoursMessage !== null && + queue.outOfHoursMessage !== "" && + !isNil(schedule) + ) { + const startTimeA = moment(schedule.startTimeA, "HH:mm"); + const endTimeA = moment(schedule.endTimeA, "HH:mm"); + const startTimeB = moment(schedule.startTimeB, "HH:mm"); + const endTimeB = moment(schedule.endTimeB, "HH:mm"); + + if (now.isBefore(startTimeA) || now.isAfter(endTimeA) && (now.isBefore(startTimeB) || now.isAfter(endTimeB))) { + const body = `${queue.outOfHoursMessage}`; + console.log('body:23801', body) + const debouncedSentMessage = debounce( + async () => { + await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net" + }`, + { + text: body + } + ); + }, + 3000, + ticket.id + ); + debouncedSentMessage(); + return; + } + } + } + + } + } catch (e) { + Sentry.captureException(e); + console.log(e); + } + + //openai na conexao + if ( + !ticket.queue && + !isGroup && + !msg.key.fromMe && + !ticket.userId && + !isNil(whatsapp.promptId) + ) { + await handleOpenAi(msg, wbot, ticket, contact, mediaSent); + } + + //integraçao na conexao + if ( + !msg.key.fromMe && + !ticket.isGroup && + !ticket.queue && + !ticket.user && + ticket.chatbot && + !isNil(whatsapp.integrationId) && + !ticket.useIntegration + ) { + + const integrations = await ShowQueueIntegrationService(whatsapp.integrationId, companyId); + + await handleMessageIntegration(msg, wbot, integrations, ticket) + + return + } + + //openai na fila + if ( + !isGroup && + !msg.key.fromMe && + !ticket.userId && + !isNil(ticket.promptId) && + ticket.useIntegration && + ticket.queueId + + ) { + await handleOpenAi(msg, wbot, ticket, contact, mediaSent); + } + + if ( + !msg.key.fromMe && + !ticket.isGroup && + !ticket.userId && + ticket.integrationId && + ticket.useIntegration && + ticket.queue + ) { + + console.log("entrou no type 1974") + const integrations = await ShowQueueIntegrationService(ticket.integrationId, companyId); + + await handleMessageIntegration(msg, wbot, integrations, ticket) + + } + + if ( + !ticket.queue && + !ticket.isGroup && + !msg.key.fromMe && + !ticket.userId && + whatsapp.queues.length >= 1 && + !ticket.useIntegration + ) { + + await verifyQueue(wbot, msg, ticket, contact); + + if (ticketTraking.chatbotAt === null) { + await ticketTraking.update({ + chatbotAt: moment().toDate(), + }) + } + } + + const dontReadTheFirstQuestion = ticket.queue === null; + + await ticket.reload(); + + try { + //Fluxo fora do expediente + if (!msg.key.fromMe && scheduleType && ticket.queueId !== null && ticket.status !== "open") { + /** + * Tratamento para envio de mensagem quando a fila está fora do expediente + */ + const queue = await Queue.findByPk(ticket.queueId); + + const { schedules }: any = queue; + const now = moment(); + const weekday = now.format("dddd").toLowerCase(); + let schedule = null; + + if (Array.isArray(schedules) && schedules.length > 0) { + schedule = schedules.find( + s => + s.weekdayEn === weekday && + s.startTimeA !== "" && + s.startTimeA !== null && + s.endTimeA !== "" && + s.endTimeA !== null + ); + } + + if ( + scheduleType.value === "queue" && + queue.outOfHoursMessage !== null && + queue.outOfHoursMessage !== "" && + !isNil(schedule) + ) { + const startTimeA = moment(schedule.startTimeA, "HH:mm"); + const endTimeA = moment(schedule.endTimeA, "HH:mm"); + const startTimeB = moment(schedule.startTimeB, "HH:mm"); + const endTimeB = moment(schedule.endTimeB, "HH:mm"); + + if (now.isBefore(startTimeA) || now.isAfter(endTimeA) && (now.isBefore(startTimeB) || now.isAfter(endTimeB))) { + const body = queue.outOfHoursMessage; + console.log('body158964153', body) + const debouncedSentMessage = debounce( + async () => { + await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net" + }`, + { + text: body + } + ); + }, + 3000, + ticket.id + ); + debouncedSentMessage(); + return; + } + } + } + } catch (e) { + Sentry.captureException(e); + console.log(e); + } + + + + if (!whatsapp?.queues?.length && !ticket.userId && !isGroup && !msg.key.fromMe) { + + const lastMessage = await Message.findOne({ + where: { + ticketId: ticket.id, + fromMe: true + }, + order: [["createdAt", "DESC"]] + }); + + if (lastMessage && lastMessage.body.includes(whatsapp.greetingMessage)) { + return; + } + + if (whatsapp.greetingMessage) { + + console.log('whatsapp.greetingMessage', whatsapp.greetingMessage) + const debouncedSentMessage = debounce( + async () => { + await wbot.sendMessage( + `${ticket.contact.number}@${ticket.isGroup ? "g.us" : "s.whatsapp.net" + }`, + { + text: whatsapp.greetingMessage + } + ); + }, + 1000, + ticket.id + ); + debouncedSentMessage(); + return; + } + + } + + + if (whatsapp.queues.length == 1 && ticket.queue) { + if (ticket.chatbot && !msg.key.fromMe) { + await handleChartbot(ticket, msg, wbot); + } + } + if (whatsapp.queues.length > 1 && ticket.queue) { + if (ticket.chatbot && !msg.key.fromMe) { + await handleChartbot(ticket, msg, wbot, dontReadTheFirstQuestion); + } + } + + } catch (err) { + console.log(err) + Sentry.captureException(err); + logger.error(`Error handling whatsapp message: Err: ${err}`); + } +}; + + +const handleMsgAck = async ( + msg: WAMessage, + chat: number | null | undefined +) => { + await new Promise((r) => setTimeout(r, 500)); + const io = getIO(); + + try { + const messageToUpdate = await Message.findByPk(msg.key.id, { + include: [ + "contact", + { + model: Message, + as: "quotedMsg", + include: ["contact"], + }, + ], + }); + + if (!messageToUpdate) return; + await messageToUpdate.update({ ack: chat }); + io.to(messageToUpdate.ticketId.toString()).emit( + `company-${messageToUpdate.companyId}-appMessage`, + { + action: "update", + message: messageToUpdate, + } + ); + } catch (err) { + Sentry.captureException(err); + logger.error(`Error handling message ack. Err: ${err}`); + } +}; + +const verifyRecentCampaign = async ( + message: proto.IWebMessageInfo, + companyId: number +) => { + if (!message.key.fromMe) { + const number = message.key.remoteJid.replace(/\D/g, ""); + const campaigns = await Campaign.findAll({ + where: { companyId, status: "EM_ANDAMENTO", confirmation: true }, + }); + if (campaigns) { + const ids = campaigns.map((c) => c.id); + const campaignShipping = await CampaignShipping.findOne({ + where: { campaignId: { [Op.in]: ids }, number, confirmation: null }, + }); + + if (campaignShipping) { + await campaignShipping.update({ + confirmedAt: moment(), + confirmation: true, + }); + await campaignQueue.add( + "DispatchCampaign", + { + campaignShippingId: campaignShipping.id, + campaignId: campaignShipping.campaignId, + }, + { + delay: parseToMilliseconds(randomValue(0, 10)), + } + ); + } + } + } +}; + +const verifyCampaignMessageAndCloseTicket = async ( + message: proto.IWebMessageInfo, + companyId: number +) => { + const io = getIO(); + const body = getBodyMessage(message); + const isCampaign = /\u200c/.test(body); + if (message.key.fromMe && isCampaign) { + const messageRecord = await Message.findOne({ + where: { id: message.key.id!, companyId }, + }); + const ticket = await Ticket.findByPk(messageRecord.ticketId); + await ticket.update({ status: "closed" }); + + io.to(`company-${ticket.companyId}-open`) + .to(`queue-${ticket.queueId}-open`) + .emit(`company-${ticket.companyId}-ticket`, { + action: "delete", + ticket, + ticketId: ticket.id, + }); + + io.to(`company-${ticket.companyId}-${ticket.status}`) + .to(`queue-${ticket.queueId}-${ticket.status}`) + .to(ticket.id.toString()) + .emit(`company-${ticket.companyId}-ticket`, { + action: "update", + ticket, + ticketId: ticket.id, + }); + } +}; + +const filterMessages = (msg: WAMessage): boolean => { + if (msg.message?.protocolMessage) return false; + + if ( + [ + WAMessageStubType.REVOKE, + WAMessageStubType.E2E_DEVICE_CHANGED, + WAMessageStubType.E2E_IDENTITY_CHANGED, + WAMessageStubType.CIPHERTEXT + ].includes(msg.messageStubType as WAMessageStubType) + ) + return false; + + return true; +}; + +const wbotMessageListener = async (wbot: Session, companyId: number): Promise => { + try { + wbot.ev.on("messages.upsert", async (messageUpsert: ImessageUpsert) => { + const messages = messageUpsert.messages + .filter(filterMessages) + .map(msg => msg); + + if (!messages) return; + + messages.forEach(async (message: proto.IWebMessageInfo) => { + + const messageExists = await Message.count({ + where: { id: message.key.id!, companyId } + }); + + if (!messageExists) { + + // console.log('body-------------------:', message); + await handleMessage(message, wbot, companyId); + await verifyRecentCampaign(message, companyId); + await verifyCampaignMessageAndCloseTicket(message, companyId); + } + }); + }); + + wbot.ev.on("messages.update", (messageUpdate: WAMessageUpdate[]) => { + if (messageUpdate.length === 0) return; + messageUpdate.forEach(async (message: WAMessageUpdate) => { + (wbot as WASocket)!.readMessages([message.key]) + + const msgUp = { ...messageUpdate } + if (msgUp['0']?.update.messageStubType === 1 && msgUp['0']?.key.remoteJid !== 'status@broadcast') { + MarkDeleteWhatsAppMessage(msgUp['0']?.key.remoteJid, null, msgUp['0']?.key.id, companyId) + } + + handleMsgAck(message, message.update.status); + }); + }); + + // wbot.ev.on("messages.set", async (messageSet: IMessage) => { + // messageSet.messages.filter(filterMessages).map(msg => msg); + // }); + } catch (error) { + Sentry.captureException(error); + logger.error(`Error handling wbot message listener. Err: ${error}`); + } +}; + +export { handleMessage, wbotMessageListener }; \ No newline at end of file diff --git a/backend/src/services/WbotServices/wbotMonitor.ts b/backend/src/services/WbotServices/wbotMonitor.ts new file mode 100644 index 0000000..7254140 --- /dev/null +++ b/backend/src/services/WbotServices/wbotMonitor.ts @@ -0,0 +1,126 @@ +import { + WASocket, + BinaryNode, + Contact as BContact +} from "@whiskeysockets/baileys"; +import * as Sentry from "@sentry/node"; + +import { Op } from "sequelize"; +// import { getIO } from "../../libs/socket"; +import { Store } from "../../libs/store"; +import Contact from "../../models/Contact"; +import Setting from "../../models/Setting"; +import Ticket from "../../models/Ticket"; +import Whatsapp from "../../models/Whatsapp"; +import { logger } from "../../utils/logger"; +import createOrUpdateBaileysService from "../BaileysServices/CreateOrUpdateBaileysService"; +import CreateMessageService from "../MessageServices/CreateMessageService"; +import { debounce } from "../../helpers/Debounce"; + +type Session = WASocket & { + id?: number; + store?: Store; +}; + +interface IContact { + contacts: BContact[]; +} + +const wbotMonitor = async ( + wbot: Session, + whatsapp: Whatsapp, + companyId: number +): Promise => { + try { + wbot.ev.on("call", async call => { + try { + if (call.length > 0) { + const sendMsgCall = await Setting.findOne({ + where: { key: "call", companyId } + }); + + if (sendMsgCall.value === "disabled") { + const callId = call[0].id; + const from = call[0].from; + + await wbot.rejectCall(callId, from).then(async () => { + const debouncedSentMessage = debounce( + async () => { + await wbot.sendMessage(from, { + text: "*Mensagem Automática:*\nAs chamadas de voz e vídeo estão desabilitas para esse WhatsApp, favor enviar uma mensagem de texto. Obrigado" + }); + + const number = from.split(":").shift(); + + const contact = await Contact.findOne({ + where: { companyId, number } + }); + + const ticket = await Ticket.findOne({ + where: { + contactId: contact.id, + whatsappId: wbot.id, + //status: { [Op.or]: ["close"] }, + companyId + } + }); + // se não existir o ticket não faz nada. + if (!ticket) return; + + const date = new Date(); + const hours = date.getHours(); + const minutes = date.getMinutes(); + + const body = `Chamada de voz/vídeo perdida às ${hours}:${minutes}`; + const messageData = { + id: callId, + ticketId: ticket.id, + contactId: contact.id, + body, + fromMe: false, + mediaType: "call_log", + read: true, + quotedMsgId: null, + ack: 1 + }; + + await ticket.update({ + lastMessage: body + }); + + if (ticket.status === "closed") { + await ticket.update({ + status: "pending" + }); + } + + await CreateMessageService({ + messageData, + companyId: companyId + }); + }, + 3000, + Number(callId.replace(/\D/g, "")) + ); + debouncedSentMessage(); + }); + } + } + } catch (error) { + logger.error("Error handling call:", error); + } + }); + + wbot.ev.on("contacts.upsert", async (contacts: BContact[]) => { + await createOrUpdateBaileysService({ + whatsappId: whatsapp.id, + contacts + }); + }); + } catch (err) { + Sentry.captureException(err); + logger.error(err); + } +}; + +export default wbotMonitor; \ No newline at end of file diff --git a/backend/src/services/WhatsappService/AssociateWhatsappQueue.ts b/backend/src/services/WhatsappService/AssociateWhatsappQueue.ts new file mode 100644 index 0000000..5f840f7 --- /dev/null +++ b/backend/src/services/WhatsappService/AssociateWhatsappQueue.ts @@ -0,0 +1,12 @@ +import Whatsapp from "../../models/Whatsapp"; + +const AssociateWhatsappQueue = async ( + whatsapp: Whatsapp, + queueIds: number[] +): Promise => { + await whatsapp.$set("queues", queueIds); + + await whatsapp.reload(); +}; + +export default AssociateWhatsappQueue; diff --git a/backend/src/services/WhatsappService/CreateWhatsAppService.ts b/backend/src/services/WhatsappService/CreateWhatsAppService.ts new file mode 100644 index 0000000..b9b4ae8 --- /dev/null +++ b/backend/src/services/WhatsappService/CreateWhatsAppService.ts @@ -0,0 +1,178 @@ +import * as Yup from "yup"; + +import AppError from "../../errors/AppError"; +import Whatsapp from "../../models/Whatsapp"; +import Company from "../../models/Company"; +import Plan from "../../models/Plan"; +import AssociateWhatsappQueue from "./AssociateWhatsappQueue"; + +interface Request { + name: string; + companyId: number; + queueIds?: number[]; + greetingMessage?: string; + complationMessage?: string; + outOfHoursMessage?: string; + ratingMessage?: string; + status?: string; + isDefault?: boolean; + token?: string; + provider?: string; + //sendIdQueue?: number; + //timeSendQueue?: number; + transferQueueId?: number; + timeToTransfer?: number; + promptId?: number; + maxUseBotQueues?: number; + timeUseBotQueues?: number; + expiresTicket?: number; + expiresInactiveMessage?: string; +} + +interface Response { + whatsapp: Whatsapp; + oldDefaultWhatsapp: Whatsapp | null; +} + +const CreateWhatsAppService = async ({ + name, + status = "OPENING", + queueIds = [], + greetingMessage, + complationMessage, + outOfHoursMessage, + ratingMessage, + isDefault = false, + companyId, + token = "", + provider = "beta", + //timeSendQueue, + //sendIdQueue, + transferQueueId, + timeToTransfer, + promptId, + maxUseBotQueues = 3, + timeUseBotQueues = 0, + expiresTicket = 0, + expiresInactiveMessage = "" +}: Request): Promise => { + const company = await Company.findOne({ + where: { + id: companyId + }, + include: [{ model: Plan, as: "plan" }] + }); + + if (company !== null) { + const whatsappCount = await Whatsapp.count({ + where: { + companyId + } + }); + + if (whatsappCount >= company.plan.connections) { + throw new AppError( + `Número máximo de conexões já alcançado: ${whatsappCount}` + ); + } + } + + const schema = Yup.object().shape({ + name: Yup.string() + .required() + .min(2) + .test( + "Check-name", + "Esse nome já está sendo utilizado por outra conexão", + async value => { + if (!value) return false; + const nameExists = await Whatsapp.findOne({ + where: { name: value, companyId} + }); + return !nameExists; + } + ), + isDefault: Yup.boolean().required() + }); + + try { + await schema.validate({ name, status, isDefault }); + } catch (err: any) { + throw new AppError(err.message); + } + + const whatsappFound = await Whatsapp.findOne({ where: { companyId } }); + + isDefault = !whatsappFound; + + let oldDefaultWhatsapp: Whatsapp | null = null; + + if (isDefault) { + oldDefaultWhatsapp = await Whatsapp.findOne({ + where: { isDefault: true, companyId } + }); + if (oldDefaultWhatsapp) { + await oldDefaultWhatsapp.update({ isDefault: false, companyId }); + } + } + + if (queueIds.length > 1 && !greetingMessage) { + throw new AppError("ERR_WAPP_GREETING_REQUIRED"); + } + + if (token !== null && token !== "") { + const tokenSchema = Yup.object().shape({ + token: Yup.string() + .required() + .min(2) + .test( + "Check-token", + "This whatsapp token is already used.", + async value => { + if (!value) return false; + const tokenExists = await Whatsapp.findOne({ + where: { token: value } + }); + return !tokenExists; + } + ) + }); + + try { + await tokenSchema.validate({ token }); + } catch (err: any) { + throw new AppError(err.message); + } + } + + const whatsapp = await Whatsapp.create( + { + name, + status, + greetingMessage, + complationMessage, + outOfHoursMessage, + ratingMessage, + isDefault, + companyId, + token, + provider, + //timeSendQueue, + //sendIdQueue, + transferQueueId, + timeToTransfer, + promptId, + maxUseBotQueues, + timeUseBotQueues, + expiresTicket, + expiresInactiveMessage + }, + { include: ["queues"] } + ); + + await AssociateWhatsappQueue(whatsapp, queueIds); + + return { whatsapp, oldDefaultWhatsapp }; +}; + +export default CreateWhatsAppService; diff --git a/backend/src/services/WhatsappService/DeleteWhatsAppService.ts b/backend/src/services/WhatsappService/DeleteWhatsAppService.ts new file mode 100644 index 0000000..ff516b8 --- /dev/null +++ b/backend/src/services/WhatsappService/DeleteWhatsAppService.ts @@ -0,0 +1,16 @@ +import Whatsapp from "../../models/Whatsapp"; +import AppError from "../../errors/AppError"; + +const DeleteWhatsAppService = async (id: string): Promise => { + const whatsapp = await Whatsapp.findOne({ + where: { id } + }); + + if (!whatsapp) { + throw new AppError("ERR_NO_WAPP_FOUND", 404); + } + + await whatsapp.destroy(); +}; + +export default DeleteWhatsAppService; diff --git a/backend/src/services/WhatsappService/ListWhatsAppsService.ts b/backend/src/services/WhatsappService/ListWhatsAppsService.ts new file mode 100644 index 0000000..e1e51a7 --- /dev/null +++ b/backend/src/services/WhatsappService/ListWhatsAppsService.ts @@ -0,0 +1,36 @@ +import { FindOptions } from "sequelize/types"; +import Queue from "../../models/Queue"; +import Whatsapp from "../../models/Whatsapp"; + +interface Request { + companyId: number; + session?: number | string; +} + +const ListWhatsAppsService = async ({ + session, + companyId +}: Request): Promise => { + const options: FindOptions = { + where: { + companyId + }, + include: [ + { + model: Queue, + as: "queues", + attributes: ["id", "name", "color", "greetingMessage"] + } + ] + }; + + if (session !== undefined && session == 0) { + options.attributes = { exclude: ["session"] }; + } + + const whatsapps = await Whatsapp.findAll(options); + + return whatsapps; +}; + +export default ListWhatsAppsService; diff --git a/backend/src/services/WhatsappService/ShowWhatsAppService.ts b/backend/src/services/WhatsappService/ShowWhatsAppService.ts new file mode 100644 index 0000000..8793438 --- /dev/null +++ b/backend/src/services/WhatsappService/ShowWhatsAppService.ts @@ -0,0 +1,46 @@ +import Whatsapp from "../../models/Whatsapp"; +import AppError from "../../errors/AppError"; +import Queue from "../../models/Queue"; +import QueueOption from "../../models/QueueOption"; +import { FindOptions } from "sequelize/types"; +import Prompt from "../../models/Prompt"; + +const ShowWhatsAppService = async ( + id: string | number, + companyId: number, + session?: any +): Promise => { + const findOptions: FindOptions = { + include: [ + { + model: Queue, + as: "queues", + attributes: ["id", "name", "color", "greetingMessage", "integrationId", "promptId", "mediaPath", "mediaName"], + include: [{ model: QueueOption, as: "options" }] + }, + { + model: Prompt, + as: "prompt", + } + ], + order: [["queues", "orderQueue", "ASC"]] + }; + + if (session !== undefined && session == 0) { + findOptions.attributes = { exclude: ["session"] }; + } + + const whatsapp = await Whatsapp.findByPk(id, findOptions); + + if (whatsapp?.companyId !== companyId) { + throw new AppError("Não é possível acessar registros de outra empresa"); + } + + if (!whatsapp) { + throw new AppError("ERR_NO_WAPP_FOUND", 404); + } + + return whatsapp; +}; + +export default ShowWhatsAppService; diff --git a/backend/src/services/WhatsappService/UpdateWhatsAppService.ts b/backend/src/services/WhatsappService/UpdateWhatsAppService.ts new file mode 100644 index 0000000..9634ce2 --- /dev/null +++ b/backend/src/services/WhatsappService/UpdateWhatsAppService.ts @@ -0,0 +1,130 @@ +import * as Yup from "yup"; +import { Op } from "sequelize"; + +import AppError from "../../errors/AppError"; +import Whatsapp from "../../models/Whatsapp"; +import ShowWhatsAppService from "./ShowWhatsAppService"; +import AssociateWhatsappQueue from "./AssociateWhatsappQueue"; + +interface WhatsappData { + name?: string; + status?: string; + session?: string; + isDefault?: boolean; + greetingMessage?: string; + complationMessage?: string; + outOfHoursMessage?: string; + ratingMessage?: string; + queueIds?: number[]; + token?: string; + //sendIdQueue?: number; + //timeSendQueue?: number; + transferQueueId?: number; + timeToTransfer?: number; + promptId?: number; + maxUseBotQueues?: number; + timeUseBotQueues?: number; + expiresTicket?: number; + expiresInactiveMessage?: string; + +} + +interface Request { + whatsappData: WhatsappData; + whatsappId: string; + companyId: number; +} + +interface Response { + whatsapp: Whatsapp; + oldDefaultWhatsapp: Whatsapp | null; +} + +const UpdateWhatsAppService = async ({ + whatsappData, + whatsappId, + companyId +}: Request): Promise => { + const schema = Yup.object().shape({ + name: Yup.string().min(2), + status: Yup.string(), + isDefault: Yup.boolean() + }); + + const { + name, + status, + isDefault, + session, + greetingMessage, + complationMessage, + outOfHoursMessage, + ratingMessage, + queueIds, + token, + //timeSendQueue, + //sendIdQueue = null, + transferQueueId, + timeToTransfer, + promptId, + maxUseBotQueues, + timeUseBotQueues, + expiresTicket, + expiresInactiveMessage + } = whatsappData; + + try { + await schema.validate({ name, status, isDefault }); + } catch (err: any) { + throw new AppError(err.message); + } + + if (queueIds.length > 1 && !greetingMessage) { + throw new AppError("ERR_WAPP_GREETING_REQUIRED"); + } + + let oldDefaultWhatsapp: Whatsapp | null = null; + + if (isDefault) { + oldDefaultWhatsapp = await Whatsapp.findOne({ + where: { + isDefault: true, + id: { [Op.not]: whatsappId }, + companyId + } + }); + if (oldDefaultWhatsapp) { + await oldDefaultWhatsapp.update({ isDefault: false }); + } + } + + const whatsapp = await ShowWhatsAppService(whatsappId, companyId); + + await whatsapp.update({ + name, + status, + session, + greetingMessage, + complationMessage, + outOfHoursMessage, + ratingMessage, + isDefault, + companyId, + token, + //timeSendQueue, + //sendIdQueue, + transferQueueId, + timeToTransfer, + promptId, + maxUseBotQueues, + timeUseBotQueues, + expiresTicket, + expiresInactiveMessage + }); + + await AssociateWhatsappQueue(whatsapp, queueIds); + + return { whatsapp, oldDefaultWhatsapp }; +}; + +export default UpdateWhatsAppService; diff --git a/backend/src/utils/global.ts b/backend/src/utils/global.ts new file mode 100644 index 0000000..6d59cba --- /dev/null +++ b/backend/src/utils/global.ts @@ -0,0 +1,2 @@ + +export const map_msg = new Map(); diff --git a/backend/src/utils/logger.ts b/backend/src/utils/logger.ts new file mode 100644 index 0000000..1b83518 --- /dev/null +++ b/backend/src/utils/logger.ts @@ -0,0 +1,22 @@ +import pino from 'pino'; +import moment from 'moment-timezone'; + +// Função para obter o timestamp com fuso horário +const timezoned = () => { + return moment().tz('America/Sao_Paulo').format('DD-MM-YYYY HH:mm:ss'); +}; + +const logger = pino({ + transport: { + target: 'pino-pretty', + options: { + colorize: true, + levelFirst: true, + translateTime: 'SYS:dd-mm-yyyy HH:MM:ss', // Use this para tradução de tempo + ignore: "pid,hostname" + }, + }, + timestamp: () => `,"time":"${timezoned()}"`, // Adiciona o timestamp formatado +}); + +export { logger }; diff --git a/backend/src/wbotTransferTicketQueue.ts b/backend/src/wbotTransferTicketQueue.ts new file mode 100644 index 0000000..1bd32ba --- /dev/null +++ b/backend/src/wbotTransferTicketQueue.ts @@ -0,0 +1,82 @@ +import { Op } from "sequelize"; +import TicketTraking from "./models/TicketTraking"; +import { format } from "date-fns"; +import moment from "moment"; +import Ticket from "./models/Ticket"; +import Whatsapp from "./models/Whatsapp"; +import { getIO } from "./libs/socket"; +import { logger } from "./utils/logger"; +import ShowTicketService from "./services/TicketServices/ShowTicketService"; + + +export const TransferTicketQueue = async (): Promise => { + + const io = getIO(); + + //buscar os tickets que em pendentes e sem fila + const tickets = await Ticket.findAll({ + where: { + status: "pending", + queueId: { + [Op.is]: null + }, + }, + + }); + + // varrer os tickets e verificar se algum deles está com o tempo estourado + tickets.forEach(async ticket => { + + + + const wpp = await Whatsapp.findOne({ + where: { + id: ticket.whatsappId + } + }); + + if (!wpp || !wpp.timeToTransfer || !wpp.transferQueueId || wpp.timeToTransfer == 0) return; + + let dataLimite = new Date(ticket.updatedAt); + dataLimite.setMinutes(dataLimite.getMinutes() + wpp.timeToTransfer); + + if (new Date() > dataLimite) { + + await ticket.update({ + + queueId: wpp.transferQueueId, + + }); + + const ticketTraking = await TicketTraking.findOne({ + where: { + ticketId: ticket.id + }, + order: [["createdAt", "DESC"]] + }); + + await ticketTraking.update({ + queuedAt: moment().toDate(), + queueId: wpp.transferQueueId, + }); + + const currentTicket = await ShowTicketService(ticket.id, ticket.companyId); + + io.to(ticket.status) + .to("notification") + .to(ticket.id.toString()) + .emit(`company-${ticket.companyId}-ticket`, { + action: "update", + ticket: currentTicket, + traking: "created ticket 33" + }); + + logger.info(`Transferencia de ticket automatica ticket id ${ticket.id} para a fila ${wpp.transferQueueId}`); + + } + + + }); + + +} diff --git a/backend/tsconfig.json b/backend/tsconfig.json new file mode 100644 index 0000000..2e566a3 --- /dev/null +++ b/backend/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "outDir": "./dist", + "strict": false, + "strictPropertyInitialization": false, + "esModuleInterop": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "types": ["node"] + }, + "exclude": ["public"] +} diff --git a/frontend/.env b/frontend/.env new file mode 100644 index 0000000..ccc3c4d --- /dev/null +++ b/frontend/.env @@ -0,0 +1,2 @@ +REACT_APP_BACKEND_URL=https://api.zapxpress.com.br +REACT_APP_HOURS_CLOSE_TICKETS_AUTO = 24 diff --git a/frontend/.env.exemple b/frontend/.env.exemple new file mode 100644 index 0000000..4d65288 --- /dev/null +++ b/frontend/.env.exemple @@ -0,0 +1,2 @@ +REACT_APP_BACKEND_URL=https://url front +REACT_APP_HOURS_CLOSE_TICKETS_AUTO = 24 diff --git a/frontend/.prettierrc b/frontend/.prettierrc new file mode 100644 index 0000000..d9b5508 --- /dev/null +++ b/frontend/.prettierrc @@ -0,0 +1,7 @@ +{ + "trailingComma": "es5", + "tabWidth": 4, + "semi": true, + "singleQuote": false, + "printWidth": 120 +} \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000..cfa988a --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,38393 @@ +{ + "name": "frontend", + "version": "0.1.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "frontend", + "version": "0.1.0", + "dependencies": { + "@date-io/date-fns": "^2.14.0", + "@date-io/moment": "^3.0.0", + "@emotion/styled": "^11.10.6", + "@floating-ui/utils": "^0.2.4", + "@material-ui/core": "4.12.3", + "@material-ui/icons": "^4.11.3", + "@material-ui/lab": "^4.0.0-alpha.56", + "@material-ui/pickers": "^3.3.10", + "@material-ui/styles": "^4.11.5", + "@mui/icons-material": "^5.14.1", + "@mui/material": "^5.10.13", + "@mui/x-date-pickers": "^6.0.1", + "@testing-library/jest-dom": "^5.11.4", + "@testing-library/react": "^11.0.4", + "@testing-library/user-event": "^12.1.7", + "async-mutex": "^0.5.0", + "axios": "^0.21.1", + "bootstrap": "^5.2.3", + "chart.js": "^3.9.1", + "chartjs-plugin-datalabels": "^2.1.0", + "compressorjs": "^1.2.1", + "context": "^4.0.0", + "date-fns": "^2.16.1", + "emoji-mart": "^3.0.0", + "express": "^4.19.2", + "formik": "^2.2.0", + "formik-material-ui": "^3.0.1", + "gn-api-sdk-node": "^3.0.2", + "html2pdf.js": "^0.10.2", + "i18next": "^19.8.2", + "i18next-browser-languagedetector": "^6.0.1", + "jsonwebtoken": "^9.0.2", + "markdown-to-jsx": "^7.1.0", + "material-ui-color": "^1.2.0", + "material-ui-nested-menu-item": "^1.0.2", + "mic-recorder-to-mp3": "^2.2.2", + "moment": "^2.29.1", + "path-browserify": "^1.0.1", + "qrcode.react": "^1.0.0", + "query-string": "^7.0.0", + "react": "^17.0.2", + "react-big-calendar": "^1.8.7", + "react-bootstrap": "^2.7.0", + "react-chartjs-2": "^4.3.1", + "react-color": "^2.19.3", + "react-copy-to-clipboard": "^5.1.0", + "react-csv": "^2.2.2", + "react-currency-format": "^1.1.0", + "react-dom": "^17.0.2", + "react-feather": "^2.0.10", + "react-icons": "^4.4.0", + "react-input-mask": "^2.0.4", + "react-jwt": "^1.2.1", + "react-modal-image": "^2.5.0", + "react-number-format": "^4.6.4", + "react-qr-code": "^2.0.7", + "react-query": "^3.39.3", + "react-router-dom": "^5.2.0", + "react-scripts": "^5.0.1", + "react-text-mask": "^5.5.0", + "react-to-print": "^3.0.2", + "react-toastify": "9.0.0", + "react-trello": "^2.2.11", + "recharts": "^2.12.7", + "socket.io-client": "^4.7.5", + "styled-components": "^5.3.5", + "text-mask-addons": "^3.8.0", + "use-debounce": "^7.0.0", + "use-sound": "^2.0.1", + "uuid": "^8.3.2", + "vcard-parser": "^1.0.0", + "xlsx": "^0.18.5", + "yup": "^0.32.8" + }, + "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==" + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/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==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "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==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/eslint-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.9.tgz", + "integrity": "sha512-5UXfgpK0j0Xr/xIdgdLEhOFxaDZ0bRPWJJchRpqOSur/3rZoPbqqki5mm0p4NE2cs28krBEiSM2MB7//afRSQQ==", + "license": "MIT", + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, + "node_modules/@babel/eslint-parser/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz", + "integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "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==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", + "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz", + "integrity": "sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "regexpu-core": "^6.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/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/@babel/helper-define-polyfill-provider/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/@babel/helper-member-expression-to-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", + "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz", + "integrity": "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", + "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", + "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", + "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", + "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", + "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", + "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.25.9.tgz", + "integrity": "sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-decorators": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", + "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz", + "integrity": "sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz", + "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", + "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "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==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "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==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-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==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", + "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz", + "integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz", + "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", + "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", + "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", + "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", + "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", + "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/template": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", + "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", + "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", + "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", + "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz", + "integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==", + "license": "MIT", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", + "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.25.9.tgz", + "integrity": "sha512-/VVukELzPDdci7UUsWQaSkhgnjIWXnIyRpM02ldxaVoFK96c41So8JcKT3m0gYjyv7j5FNPGS5vfELrWalkbDA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-flow": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz", + "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", + "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", + "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", + "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", + "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", + "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", + "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz", + "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-simple-access": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", + "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", + "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", + "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz", + "integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", + "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", + "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", + "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", + "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", + "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", + "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", + "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", + "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.9.tgz", + "integrity": "sha512-Ncw2JFsJVuvfRsa2lSHiC55kETQVLSnsYGQ1JDDwkUeWGTL/8Tom8aLTnlqgoeuopWrbbGndrc9AlLYrIosrow==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz", + "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", + "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz", + "integrity": "sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==", + "license": "MIT", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz", + "integrity": "sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", + "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", + "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", + "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz", + "integrity": "sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", + "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", + "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", + "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz", + "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz", + "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.9.tgz", + "integrity": "sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", + "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", + "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", + "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", + "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz", + "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.25.9", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.25.9", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.25.9", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.25.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.25.9", + "@babel/plugin-transform-typeof-symbol": "^7.25.9", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.38.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.25.9.tgz", + "integrity": "sha512-D3to0uSPiWE7rBrdIICCd0tJSIGpLaaGptna2+w7Pft5xMqLpA1sz99DK5TZ1TjGbdQ/VI1eCSZ06dv3lT4JOw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-transform-react-display-name": "^7.25.9", + "@babel/plugin-transform-react-jsx": "^7.25.9", + "@babel/plugin-transform-react-jsx-development": "^7.25.9", + "@babel/plugin-transform-react-pure-annotations": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", + "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", + "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime/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/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/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/@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==", + "license": "MIT" + }, + "node_modules/@babel/types": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "license": "MIT" + }, + "node_modules/@csstools/normalize.css": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.1.1.tgz", + "integrity": "sha512-YAYeJ+Xqh7fUou1d1j9XHl44BmsuThiTr4iNrgCQ3J27IbhXsxXDGZ1cXv8Qvs99d4rBbLiSKy3+WZiet32PcQ==", + "license": "CC0-1.0" + }, + "node_modules/@csstools/postcss-cascade-layers": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", + "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", + "license": "CC0-1.0", + "dependencies": { + "@csstools/selector-specificity": "^2.0.2", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-color-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", + "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", + "license": "CC0-1.0", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-font-format-keywords": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", + "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-hwb-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", + "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-ic-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", + "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", + "license": "CC0-1.0", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", + "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", + "license": "CC0-1.0", + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-nested-calc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz", + "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-normalize-display-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz", + "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-oklab-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", + "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", + "license": "CC0-1.0", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-progressive-custom-properties": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", + "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", + "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz", + "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-trigonometric-functions": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz", + "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-unset-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", + "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", + "license": "CC0-1.0", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", + "license": "CC0-1.0", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.10" + } + }, + "node_modules/@date-io/core": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@date-io/core/-/core-2.17.0.tgz", + "integrity": "sha512-+EQE8xZhRM/hsY0CDTVyayMDDY5ihc4MqXCrPxooKw19yAzUIC6uUqsZeaOFNL9YKTNxYKrJP5DFgE8o5xRCOw==" + }, + "node_modules/@date-io/date-fns": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@date-io/date-fns/-/date-fns-2.17.0.tgz", + "integrity": "sha512-L0hWZ/mTpy3Gx/xXJ5tq5CzHo0L7ry6KEO9/w/JWiFWFLZgiNVo3ex92gOl3zmzjHqY/3Ev+5sehAr8UnGLEng==", + "dependencies": { + "@date-io/core": "^2.17.0" + }, + "peerDependencies": { + "date-fns": "^2.0.0" + }, + "peerDependenciesMeta": { + "date-fns": { + "optional": true + } + } + }, + "node_modules/@date-io/moment": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@date-io/moment/-/moment-3.0.0.tgz", + "integrity": "sha512-yIBGP+uBK1Xp0va91uYi0KkJpdXgDWaj5xU1M39YdljQVXea3BM/6eXd7CnlCUwnGhfyanj8AdZvMvpkyjnJUg==", + "dependencies": { + "@date-io/core": "^3.0.0" + }, + "peerDependencies": { + "moment": "^2.24.0" + }, + "peerDependenciesMeta": { + "moment": { + "optional": true + } + } + }, + "node_modules/@date-io/moment/node_modules/@date-io/core": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@date-io/core/-/core-3.0.0.tgz", + "integrity": "sha512-S3j+IAQVBYNkQzchVVhX40eBkGDreBpScy9RXwTS5j2+k07+62pMVPisQ44Gq76Rqy5AOG/EZXCwBpY/jbemvA==" + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", + "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.2.0", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + }, + "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz", + "integrity": "sha512-SHetuSLvJDzuNbOdtPVbq6yMMMlLoW5Q94uDqJZqy50gcmAjxFkVqmzqSGEFq9gT2iMuIeKV1PXVWmvUhuZLlQ==", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/is-prop-valid/node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + }, + "node_modules/@emotion/react": { + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.0.tgz", + "integrity": "sha512-WkL+bw1REC2VNV1goQyfxjx1GYJkcc23CRQkXX+vZNLINyfI7o+uUn/rTGPt/xJ3bJHd5GcljgnxHf4wRw5VWQ==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/cache": "^11.13.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/react/node_modules/@emotion/cache": { + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "peer": true, + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/react/node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "peer": true + }, + "node_modules/@emotion/react/node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "peer": true + }, + "node_modules/@emotion/react/node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "peer": true + }, + "node_modules/@emotion/react/node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "peer": true + }, + "node_modules/@emotion/serialize": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.0.tgz", + "integrity": "sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA==", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.9.0", + "@emotion/utils": "^1.4.0", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/serialize/node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" + }, + "node_modules/@emotion/serialize/node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + }, + "node_modules/@emotion/serialize/node_modules/@emotion/unitless": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.9.0.tgz", + "integrity": "sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==" + }, + "node_modules/@emotion/serialize/node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/@emotion/styled": { + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz", + "integrity": "sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "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/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.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": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/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/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/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" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/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/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz", + "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/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/@humanwhocodes/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==", + "license": "MIT" + }, + "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==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "license": "BSD-3-Clause" + }, + "node_modules/@icons/material": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", + "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "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==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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/@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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/console/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/console/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/console/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/console/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/console/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/console/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "license": "MIT", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/core/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/environment/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/environment/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/fake-timers/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/globals/node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/reporters/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters/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/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/source-map/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/@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "license": "MIT", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-result/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-result/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "license": "MIT", + "dependencies": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/transform/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/@jest/transform/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform/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/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.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==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "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==", + "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==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "license": "MIT" + }, + "node_modules/@material-ui/core": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz", + "integrity": "sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw==", + "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", + "dependencies": { + "@babel/runtime": "^7.4.4", + "@material-ui/styles": "^4.11.4", + "@material-ui/system": "^4.12.1", + "@material-ui/types": "5.1.0", + "@material-ui/utils": "^4.11.2", + "@types/react-transition-group": "^4.2.0", + "clsx": "^1.0.4", + "hoist-non-react-statics": "^3.3.2", + "popper.js": "1.16.1-lts", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0", + "react-transition-group": "^4.4.0" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/material-ui" + }, + "peerDependencies": { + "@types/react": "^16.8.6 || ^17.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/core/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/@material-ui/icons": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.3.tgz", + "integrity": "sha512-IKHlyx6LDh8n19vzwH5RtHIOHl9Tu90aAAxcbWME6kp4dmvODM3UvOHJeMIDzUbd4muuJKHmlNoBN+mDY4XkBA==", + "dependencies": { + "@babel/runtime": "^7.4.4" + }, + "engines": { + "node": ">=8.0.0" + }, + "peerDependencies": { + "@material-ui/core": "^4.0.0", + "@types/react": "^16.8.6 || ^17.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/lab": { + "version": "4.0.0-alpha.61", + "resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.61.tgz", + "integrity": "sha512-rSzm+XKiNUjKegj8bzt5+pygZeckNLOr+IjykH8sYdVk7dE9y2ZuUSofiMV2bJk3qU+JHwexmw+q0RyNZB9ugg==", + "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", + "dependencies": { + "@babel/runtime": "^7.4.4", + "@material-ui/utils": "^4.11.3", + "clsx": "^1.0.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0" + }, + "engines": { + "node": ">=8.0.0" + }, + "peerDependencies": { + "@material-ui/core": "^4.12.1", + "@types/react": "^16.8.6 || ^17.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/lab/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/@material-ui/pickers": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@material-ui/pickers/-/pickers-3.3.11.tgz", + "integrity": "sha512-pDYjbjUeabapijS2FpSwK/ruJdk7IGeAshpLbKDa3PRRKRy7Nv6sXxAvUg2F+lID/NwUKgBmCYS5bzrl7Xxqzw==", + "deprecated": "This package no longer supported. It has been relaced by @mui/x-date-pickers", + "dependencies": { + "@babel/runtime": "^7.6.0", + "@date-io/core": "1.x", + "@types/styled-jsx": "^2.2.8", + "clsx": "^1.0.2", + "react-transition-group": "^4.0.0", + "rifm": "^0.7.0" + }, + "peerDependencies": { + "@date-io/core": "^1.3.6", + "@material-ui/core": "^4.0.0", + "prop-types": "^15.6.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/@material-ui/pickers/node_modules/@date-io/core": { + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@date-io/core/-/core-1.3.13.tgz", + "integrity": "sha512-AlEKV7TxjeK+jxWVKcCFrfYAk8spX9aCyiToFIiLPtfQbsjmRGLIhb5VZgptQcJdHtLXo7+m0DuurwFgUToQuA==" + }, + "node_modules/@material-ui/pickers/node_modules/@types/styled-jsx": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@types/styled-jsx/-/styled-jsx-2.2.9.tgz", + "integrity": "sha512-W/iTlIkGEyTBGTEvZCey8EgQlQ5l0DwMqi3iOXlLs2kyBwYTXHKEiU6IZ5EwoRwngL8/dGYuzezSup89ttVHLw==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@material-ui/pickers/node_modules/rifm": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rifm/-/rifm-0.7.0.tgz", + "integrity": "sha512-DSOJTWHD67860I5ojetXdEQRIBvF6YcpNe53j0vn1vp9EUb9N80EiZTxgP+FkDKorWC8PZw052kTF4C1GOivCQ==", + "dependencies": { + "@babel/runtime": "^7.3.1" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/@material-ui/styles": { + "version": "4.11.5", + "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.5.tgz", + "integrity": "sha512-o/41ot5JJiUsIETME9wVLAJrmIWL3j0R0Bj2kCOLbSfqEkKf0fmaPt+5vtblUh5eXr2S+J/8J3DaCb10+CzPGA==", + "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", + "dependencies": { + "@babel/runtime": "^7.4.4", + "@emotion/hash": "^0.8.0", + "@material-ui/types": "5.1.0", + "@material-ui/utils": "^4.11.3", + "clsx": "^1.0.4", + "csstype": "^2.5.2", + "hoist-non-react-statics": "^3.3.2", + "jss": "^10.5.1", + "jss-plugin-camel-case": "^10.5.1", + "jss-plugin-default-unit": "^10.5.1", + "jss-plugin-global": "^10.5.1", + "jss-plugin-nested": "^10.5.1", + "jss-plugin-props-sort": "^10.5.1", + "jss-plugin-rule-value-function": "^10.5.1", + "jss-plugin-vendor-prefixer": "^10.5.1", + "prop-types": "^15.7.2" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/material-ui" + }, + "peerDependencies": { + "@types/react": "^16.8.6 || ^17.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/styles/node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + }, + "node_modules/@material-ui/styles/node_modules/css-vendor": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", + "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", + "dependencies": { + "@babel/runtime": "^7.8.3", + "is-in-browser": "^1.0.2" + } + }, + "node_modules/@material-ui/styles/node_modules/csstype": { + "version": "2.6.21", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", + "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" + }, + "node_modules/@material-ui/styles/node_modules/hyphenate-style-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==" + }, + "node_modules/@material-ui/styles/node_modules/is-in-browser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", + "integrity": "sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==" + }, + "node_modules/@material-ui/styles/node_modules/jss": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss/-/jss-10.10.0.tgz", + "integrity": "sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "csstype": "^3.0.2", + "is-in-browser": "^1.1.3", + "tiny-warning": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/jss" + } + }, + "node_modules/@material-ui/styles/node_modules/jss-plugin-camel-case": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.10.0.tgz", + "integrity": "sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "hyphenate-style-name": "^1.0.3", + "jss": "10.10.0" + } + }, + "node_modules/@material-ui/styles/node_modules/jss-plugin-default-unit": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.10.0.tgz", + "integrity": "sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0" + } + }, + "node_modules/@material-ui/styles/node_modules/jss-plugin-global": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.10.0.tgz", + "integrity": "sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0" + } + }, + "node_modules/@material-ui/styles/node_modules/jss-plugin-nested": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.10.0.tgz", + "integrity": "sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0", + "tiny-warning": "^1.0.2" + } + }, + "node_modules/@material-ui/styles/node_modules/jss-plugin-props-sort": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.10.0.tgz", + "integrity": "sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0" + } + }, + "node_modules/@material-ui/styles/node_modules/jss-plugin-rule-value-function": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.10.0.tgz", + "integrity": "sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0", + "tiny-warning": "^1.0.2" + } + }, + "node_modules/@material-ui/styles/node_modules/jss-plugin-vendor-prefixer": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.10.0.tgz", + "integrity": "sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "css-vendor": "^2.0.8", + "jss": "10.10.0" + } + }, + "node_modules/@material-ui/styles/node_modules/jss/node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/@material-ui/system": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.2.tgz", + "integrity": "sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw==", + "dependencies": { + "@babel/runtime": "^7.4.4", + "@material-ui/utils": "^4.11.3", + "csstype": "^2.5.2", + "prop-types": "^15.7.2" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/material-ui" + }, + "peerDependencies": { + "@types/react": "^16.8.6 || ^17.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/system/node_modules/csstype": { + "version": "2.6.21", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", + "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" + }, + "node_modules/@material-ui/types": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz", + "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==", + "peerDependencies": { + "@types/react": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/utils": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.3.tgz", + "integrity": "sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg==", + "dependencies": { + "@babel/runtime": "^7.4.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0" + }, + "engines": { + "node": ">=8.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/@material-ui/utils/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/@mui/base": { + "version": "5.0.0-beta.40", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz", + "integrity": "sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@floating-ui/react-dom": "^2.0.8", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/base/node_modules/@floating-ui/core": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz", + "integrity": "sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==", + "dependencies": { + "@floating-ui/utils": "^0.2.7" + } + }, + "node_modules/@mui/base/node_modules/@floating-ui/dom": { + "version": "1.6.10", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.10.tgz", + "integrity": "sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.7" + } + }, + "node_modules/@mui/base/node_modules/@floating-ui/react-dom": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", + "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@mui/base/node_modules/@mui/types": { + "version": "7.2.15", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz", + "integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==", + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/base/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@mui/icons-material": { + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.16.7.tgz", + "integrity": "sha512-UrGwDJCXEszbDI7yV047BYU5A28eGJ79keTCP4cc74WyncuVrnurlmIRxaHL8YK+LI1Kzq+/JM52IAkNnv4u+Q==", + "dependencies": { + "@babel/runtime": "^7.23.9" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^5.0.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.7.tgz", + "integrity": "sha512-cwwVQxBhK60OIOqZOVLFt55t01zmarKJiJUWbk0+8s/Ix5IaUzAShqlJchxsIQ4mSrWqgcKCCXKtIlG5H+/Jmg==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/core-downloads-tracker": "^5.16.7", + "@mui/system": "^5.16.7", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.6", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^18.3.1", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/@mui/core-downloads-tracker": { + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.7.tgz", + "integrity": "sha512-RtsCt4Geed2/v74sbihWzzRs+HsIQCfclHeORh5Ynu2fS4icIKozcSubwuG7vtzq2uW3fOR1zITSP84TNt2GoQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/material/node_modules/@mui/types": { + "version": "7.2.15", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz", + "integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==", + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@mui/material/node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/@mui/system": { + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.7.tgz", + "integrity": "sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/private-theming": "^5.16.6", + "@mui/styled-engine": "^5.16.6", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.6", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/system/node_modules/@emotion/cache": { + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@mui/system/node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + }, + "node_modules/@mui/system/node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==" + }, + "node_modules/@mui/system/node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" + }, + "node_modules/@mui/system/node_modules/@mui/private-theming": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.6.tgz", + "integrity": "sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.16.6", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/system/node_modules/@mui/styled-engine": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.6.tgz", + "integrity": "sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@emotion/cache": "^11.11.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system/node_modules/@mui/types": { + "version": "7.2.15", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz", + "integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==", + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/system/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@mui/system/node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/@mui/system/node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/@mui/utils": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz", + "integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/types": "^7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils/node_modules/@mui/types": { + "version": "7.2.15", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz", + "integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==", + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@mui/x-date-pickers": { + "version": "6.20.2", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.20.2.tgz", + "integrity": "sha512-x1jLg8R+WhvkmUETRfX2wC+xJreMii78EXKLl6r3G+ggcAZlPyt0myID1Amf6hvJb9CtR7CgUo8BwR+1Vx9Ggw==", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@mui/base": "^5.0.0-beta.22", + "@mui/utils": "^5.14.16", + "@types/react-transition-group": "^4.4.8", + "clsx": "^2.0.0", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.8.6", + "@mui/system": "^5.8.0", + "date-fns": "^2.25.0 || ^3.2.0", + "date-fns-jalali": "^2.13.0-0", + "dayjs": "^1.10.7", + "luxon": "^3.0.2", + "moment": "^2.29.4", + "moment-hijri": "^2.1.2", + "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "date-fns": { + "optional": true + }, + "date-fns-jalali": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + }, + "moment-hijri": { + "optional": true + }, + "moment-jalaali": { + "optional": true + } + } + }, + "node_modules/@mui/x-date-pickers/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "license": "MIT", + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.15.tgz", + "integrity": "sha512-LFWllMA55pzB9D34w/wXUCf8+c+IYKuJDgxiZ3qMhl64KRMBHYM1I3VdGaD2BV5FNPV2/S2596bppxHbv2ZydQ==", + "license": "MIT", + "dependencies": { + "ansi-html": "^0.0.9", + "core-js-pure": "^3.23.3", + "error-stack-parser": "^2.0.6", + "html-entities": "^2.1.0", + "loader-utils": "^2.0.4", + "schema-utils": "^4.2.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "@types/webpack": "4.x || 5.x", + "react-refresh": ">=0.10.0 <1.0.0", + "sockjs-client": "^1.4.0", + "type-fest": ">=0.17.0 <5.0.0", + "webpack": ">=4.43.0 <6.0.0", + "webpack-dev-server": "3.x || 4.x || 5.x", + "webpack-hot-middleware": "2.x", + "webpack-plugin-serve": "0.x || 1.x" + }, + "peerDependenciesMeta": { + "@types/webpack": { + "optional": true + }, + "sockjs-client": { + "optional": true + }, + "type-fest": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + }, + "webpack-hot-middleware": { + "optional": true + }, + "webpack-plugin-serve": { + "optional": true + } + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@restart/hooks": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz", + "integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==", + "dependencies": { + "dequal": "^2.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/hooks/node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@restart/ui": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.8.0.tgz", + "integrity": "sha512-xJEOXUOTmT4FngTmhdjKFRrVVF0hwCLNPdatLCHkyS4dkiSK12cEu1Y0fjxktjJrdst9jJIc5J6ihMJCoWEN/g==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@popperjs/core": "^2.11.6", + "@react-aria/ssr": "^3.5.0", + "@restart/hooks": "^0.4.9", + "@types/warning": "^3.0.0", + "dequal": "^2.0.3", + "dom-helpers": "^5.2.0", + "uncontrollable": "^8.0.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, + "node_modules/@restart/ui/node_modules/@react-aria/ssr": { + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.5.tgz", + "integrity": "sha512-xEwGKoysu+oXulibNUSkXf8itW0npHHTa6c4AyYeZIJyRoegeteYuFpZUBPtIDE8RfHdNsSmE1ssOkxRnwbkuQ==", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@restart/ui/node_modules/@swc/helpers": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.12.tgz", + "integrity": "sha512-KMZNXiGibsW9kvZAO1Pam2JPTDBm+KSHMMHWdsyI/1DbIZjT2A6Gy3hblVXUMEDvUAKq+e0vL0X0o54owWji7g==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@restart/ui/node_modules/@types/warning": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz", + "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==" + }, + "node_modules/@restart/ui/node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@restart/ui/node_modules/uncontrollable": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz", + "integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==", + "peerDependencies": { + "react": ">=16.14.0" + } + }, + "node_modules/@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-node-resolve/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/@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "license": "MIT", + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/pluginutils/node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "license": "MIT" + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "license": "MIT" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", + "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==", + "license": "MIT" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + }, + "node_modules/@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "license": "Apache-2.0", + "dependencies": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", + "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", + "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", + "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", + "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", + "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", + "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", + "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", + "license": "MIT", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", + "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", + "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", + "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", + "@svgr/babel-plugin-transform-svg-component": "^5.5.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/core": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", + "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", + "license": "MIT", + "dependencies": { + "@svgr/plugin-jsx": "^5.5.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", + "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.12.6" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", + "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.12.3", + "@svgr/babel-preset": "^5.5.0", + "@svgr/hast-util-to-babel-ast": "^5.5.0", + "svg-parser": "^2.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", + "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", + "license": "MIT", + "dependencies": { + "cosmiconfig": "^7.0.0", + "deepmerge": "^4.2.2", + "svgo": "^1.2.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-svgo/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/@svgr/webpack": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", + "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/plugin-transform-react-constant-elements": "^7.12.1", + "@babel/preset-env": "^7.12.1", + "@babel/preset-react": "^7.12.5", + "@svgr/core": "^5.5.0", + "@svgr/plugin-jsx": "^5.5.0", + "@svgr/plugin-svgo": "^5.5.0", + "loader-utils": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "peer": true + }, + "node_modules/@testing-library/dom/node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "peer": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "peer": true + }, + "node_modules/@testing-library/jest-dom": { + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", + "integrity": "sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==", + "dependencies": { + "@adobe/css-tools": "^4.0.1", + "@babel/runtime": "^7.9.2", + "@types/testing-library__jest-dom": "^5.9.1", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=8", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/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==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/jest-dom/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/@testing-library/jest-dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.7.tgz", + "integrity": "sha512-tzRNp7pzd5QmbtXNG/mhdcl7Awfu/Iz1RaVHY75zTdOkmHCuzMhRL83gWHSgOAcjS3CCbyfwUHMZgRJb4kAfpA==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^7.28.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@testing-library/react/node_modules/@babel/runtime-corejs3": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.25.0.tgz", + "integrity": "sha512-BOehWE7MgQ8W8Qn0CQnMtg2tHPHPulcS/5AVpFvs2KCK1ET+0WqZqPvnpRpFN81gYoFopdIEJX9Sgjw3ZBccPg==", + "dependencies": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@testing-library/react/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@testing-library/react/node_modules/@testing-library/dom": { + "version": "7.31.2", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", + "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^4.2.2", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.6", + "lz-string": "^1.4.4", + "pretty-format": "^26.6.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@testing-library/react/node_modules/@types/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==" + }, + "node_modules/@testing-library/react/node_modules/@types/yargs": { + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@testing-library/react/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/react/node_modules/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "dependencies": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@testing-library/react/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==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/react/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/@testing-library/react/node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/@testing-library/react/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@testing-library/react/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/@testing-library/react/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/@testing-library/user-event": { + "version": "12.8.3", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.8.3.tgz", + "integrity": "sha512-IR0iWbFkgd56Bu5ZI/ej8yQwrkCv8Qydx6RzwbKz9faXazR/+5tvYKsZQgyXJiwgpcva127YO6JcWy7YlCfofQ==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "license": "ISC", + "engines": { + "node": ">=10.13.0" + } + }, + "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==", + "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.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "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==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "license": "MIT", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" + }, + "node_modules/@types/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" + }, + "node_modules/@types/eslint": { + "version": "8.56.12", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.12.tgz", + "integrity": "sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==", + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz", + "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express/node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", + "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "license": "MIT" + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "license": "MIT" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.15", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz", + "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "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==" + }, + "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==", + "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==", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "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/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", + "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.7.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.9.tgz", + "integrity": "sha512-jrTfRC7FM6nChvU7X2KqcrgquofrWLFDeYC1hKfwNWomVvrn7JIksqf344WN2X/y8xrgqBd2dJATZV4GbatBfg==", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" + }, + "node_modules/@types/q": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.8.tgz", + "integrity": "sha512-hroOstUScF6zhIi+5+x0dzqrHA1EJi+Irri6b1fxolMTqqHIV/Cg77EtnQcZqZCu8hR3mX2BzIxN4/GzI68Kfw==", + "license": "MIT" + }, + "node_modules/@types/qs": { + "version": "6.9.17", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", + "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==", + "license": "MIT" + }, + "node_modules/@types/raf": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", + "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", + "optional": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "17.0.80", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.80.tgz", + "integrity": "sha512-LrgHIu2lEtIo8M7d1FcI3BdwXWoRQwMoXOZ7+dPTW0lYREjmlHl3P0U1VD0i/9tppOuv8/sam7sOjx34TxSFbA==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "^0.16", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz", + "integrity": "sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react/node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" + }, + "node_modules/@types/scheduler": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "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==" + }, + "node_modules/@types/testing-library__jest-dom": { + "version": "5.14.9", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz", + "integrity": "sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==", + "dependencies": { + "@types/jest": "*" + } + }, + "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" + }, + "node_modules/@types/ws": { + "version": "8.5.13", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", + "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "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==", + "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==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/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/@typescript-eslint/eslint-plugin/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/@typescript-eslint/experimental-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", + "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/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/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/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/@typescript-eslint/type-utils/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/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/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/@typescript-eslint/typescript-estree/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/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "license": "ISC" + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "license": "Apache-2.0" + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "license": "BSD-3-Clause" + }, + "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==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "license": "MIT", + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "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==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/adler-32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/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/agent-base/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/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "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/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.9.tgz", + "integrity": "sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg==", + "engines": [ + "node >= 0.8.0" + ], + "license": "Apache-2.0", + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "license": "Apache-2.0", + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "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": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "license": "MIT" + }, + "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/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/argparse": { + "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" + } + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/aria-query/node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.reduce": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.7.tgz", + "integrity": "sha512-mzmiUCVwtiD4lgxYP8g7IYy8El8p2CSMePvIbTS7gchKir/L1fgJrk0yDKmAX6mnRQFKNADYIk8nNlTris5H1Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-array-method-boxes-properly": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "license": "MIT" + }, + "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/async-mutex": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", + "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "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/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/autosize": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/autosize/-/autosize-4.0.4.tgz", + "integrity": "sha512-5yxLQ22O0fCRGoxGfeLSNt3J8LB1v+umtpMnPW6XjkTWXKoN0AmXAIhelJcDtFT/Y/wYWmfE+oqU10Q0b8FhaQ==" + }, + "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/axe-core": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz", + "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==", + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "license": "MIT", + "dependencies": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-jest/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/babel-loader": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.4.1.tgz", + "integrity": "sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==", + "license": "MIT", + "dependencies": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.4", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" + } + }, + "node_modules/babel-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "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==", + "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-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-named-asset-import": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", + "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", + "peerDependencies": { + "@babel/core": "^7.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-transform-react-remove-prop-types": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", + "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==", + "license": "MIT" + }, + "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==", + "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": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-react-app": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz", + "integrity": "sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/plugin-proposal-class-properties": "^7.16.0", + "@babel/plugin-proposal-decorators": "^7.16.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", + "@babel/plugin-proposal-numeric-separator": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.0", + "@babel/plugin-proposal-private-methods": "^7.16.0", + "@babel/plugin-transform-flow-strip-types": "^7.16.0", + "@babel/plugin-transform-react-display-name": "^7.16.0", + "@babel/plugin-transform-runtime": "^7.16.4", + "@babel/preset-env": "^7.16.4", + "@babel/preset-react": "^7.16.0", + "@babel/preset-typescript": "^7.16.0", + "@babel/runtime": "^7.16.3", + "babel-plugin-macros": "^3.1.0", + "babel-plugin-transform-react-remove-prop-types": "^0.4.24" + } + }, + "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/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "license": "MIT" + }, + "node_modules/bfj": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.1.0.tgz", + "integrity": "sha512-I6MMLkn+anzNdCUp9hMRyui1HaNEUCco50lxbvNS4+EyXg8lN3nJ48PjPWtbH8UVS9CuMoaKE9U2V3l29DaRQw==", + "license": "MIT", + "dependencies": { + "bluebird": "^3.7.2", + "check-types": "^11.2.3", + "hoopy": "^0.1.4", + "jsonpath": "^1.1.1", + "tryer": "^1.0.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "license": "MIT", + "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/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "license": "MIT" + }, + "node_modules/blueimp-canvas-to-blob": { + "version": "3.29.0", + "resolved": "https://registry.npmjs.org/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.29.0.tgz", + "integrity": "sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg==" + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "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.11.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/body-parser/node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/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==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/raw-body": { + "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==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/bootstrap": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", + "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, + "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==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/broadcast-channel": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", + "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", + "dependencies": { + "@babel/runtime": "^7.7.2", + "detect-node": "^2.1.0", + "js-sha3": "0.8.0", + "microseconds": "0.2.0", + "nano-time": "1.0.0", + "oblivious-set": "1.0.0", + "rimraf": "3.0.2", + "unload": "2.2.0" + } + }, + "node_modules/broadcast-channel/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==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/broadcast-channel/node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, + "node_modules/broadcast-channel/node_modules/microseconds": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", + "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" + }, + "node_modules/broadcast-channel/node_modules/nano-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", + "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", + "dependencies": { + "big-integer": "^1.6.16" + } + }, + "node_modules/broadcast-channel/node_modules/oblivious-set": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", + "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" + }, + "node_modules/broadcast-channel/node_modules/unload": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", + "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", + "dependencies": { + "@babel/runtime": "^7.6.2", + "detect-node": "^2.0.4" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "license": "BSD-2-Clause" + }, + "node_modules/browserslist": { + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "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.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" + }, + "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==", + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "bin": { + "btoa": "bin/btoa.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "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/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "license": "MIT", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001678", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001678.tgz", + "integrity": "sha512-RR+4U/05gNtps58PEBDZcPWTgEO2MBeoPZ96aQcjmfkBWRIDfN451fW2qyDA9/+HohLLIL5GqiMwA+IB1pWarw==", + "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/canvg": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", + "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/cfb": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", + "dependencies": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk/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==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/chalk/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/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chart.js": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", + "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" + }, + "node_modules/chartjs-plugin-datalabels": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz", + "integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==", + "peerDependencies": { + "chart.js": ">=3.0.0" + } + }, + "node_modules/check-types": { + "version": "11.2.3", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz", + "integrity": "sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==", + "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==", + "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/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", + "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==" + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "license": "MIT", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css/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/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "license": "MIT", + "dependencies": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/coa/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "engines": { + "node": ">=0.8" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "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/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "license": "MIT" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz", + "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.0.2", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compressorjs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/compressorjs/-/compressorjs-1.2.1.tgz", + "integrity": "sha512-+geIjeRnPhQ+LLvvA7wxBQE5ddeLU7pJ3FsKFWirDw6veY3s9iLxAQEw7lXGHnhCJvBujEQWuNnGzZcvCvdkLQ==", + "dependencies": { + "blueimp-canvas-to-blob": "^3.29.0", + "is-blob": "^2.1.0" + } + }, + "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/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "license": "MIT" + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "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==", + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/context": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/context/-/context-4.0.0.tgz", + "integrity": "sha512-B5XTstvpRXt79RkiLR+/XqSCDPrtAsdIZAhZuBCj1bXzuHy7HVbhee+aJ/pHP/+pYrP7YAHdqDH91vfuwqD9/w==", + "dependencies": { + "vest-utils": "^0.0.5" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "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/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/copy-to-clipboard/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==" + }, + "node_modules/core-js": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz", + "integrity": "sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", + "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.39.0.tgz", + "integrity": "sha512-7fEcWwKI4rJinnK+wLTezeg2smbFFdSBP6E2kQZNbnzM2s1rpKQ6aaRteZSSg7FLU3P0HGGVo/gbpfanU36urg==", + "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/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=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==", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", + "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/css-blank-pseudo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", + "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", + "license": "CC0-1.0", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "bin": { + "css-blank-pseudo": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-has-pseudo": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", + "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", + "license": "CC0-1.0", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "bin": { + "css-has-pseudo": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "dependencies": { + "utrie": "^1.0.2" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", + "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", + "license": "MIT", + "dependencies": { + "cssnano": "^5.0.6", + "jest-worker": "^27.0.2", + "postcss": "^8.3.5", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-prefers-color-scheme": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", + "license": "CC0-1.0", + "bin": { + "css-prefers-color-scheme": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "license": "MIT" + }, + "node_modules/css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/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/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "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/cssdb": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.11.2.tgz", + "integrity": "sha512-lhQ32TFkc1X4eTefGfYPvgovRSzIMofHkigfH8nWtyRL4XJLsRhJFreRvEgKzept7x1rjBuy3J/MurXLaFxW/A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + } + ], + "license": "CC0-1.0" + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "license": "MIT", + "dependencies": { + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "license": "MIT", + "dependencies": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "license": "MIT", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "license": "MIT", + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "license": "CC0-1.0" + }, + "node_modules/csso/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/cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "license": "MIT" + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "license": "MIT", + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "license": "MIT" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "license": "BSD-2-Clause" + }, + "node_modules/data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "license": "MIT", + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/date-arithmetic": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-arithmetic/-/date-arithmetic-4.1.0.tgz", + "integrity": "sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg==" + }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/dayjs": { + "version": "1.11.12", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz", + "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "license": "MIT" + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "license": "BSD-2-Clause", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "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": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "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/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "license": "MIT" + }, + "node_modules/detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "license": "MIT", + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "license": "Apache-2.0" + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "license": "MIT" + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "license": "MIT", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "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": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "license": "MIT", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dom-helpers/node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "deprecated": "Use your platform's native DOMException instead", + "license": "MIT", + "dependencies": { + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dompurify": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.7.tgz", + "integrity": "sha512-2q4bEI+coQM8f5ez7kt2xclg1XsecaV9ASJk/54vwlfRRNQfDqJz2pzQ8t0Ix/ToBpXlVjrRIx7pFC/o8itG2Q==", + "optional": true + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "license": "MIT" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.52", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.52.tgz", + "integrity": "sha512-xtoijJTZ+qeucLBDNztDOuQBE1ksqjvNjvqFoST3nGC7fSpqJ+X6BdTBaY5BHG+IhWWmpc6b/KfpeuEDupEPOQ==", + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-mart": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-3.0.1.tgz", + "integrity": "sha512-sxpmMKxqLvcscu6mFn9ITHeZNkGzIvD0BSNFE/LJESPbCA8s1jM6bCDPjWbV31xHq7JXaxgpHxLB54RCbBZSlg==", + "dependencies": { + "@babel/runtime": "^7.0.0", + "prop-types": "^15.6.0" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.0-0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io-client": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz", + "integrity": "sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.0.0" + } + }, + "node_modules/engine.io-client/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io-client/node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io-client/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/engine.io-client/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/engine.io-client/node_modules/xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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/es-iterator-helpers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz", + "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.3", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=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": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/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": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/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", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-react-app": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", + "integrity": "sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/eslint-parser": "^7.16.3", + "@rushstack/eslint-patch": "^1.1.0", + "@typescript-eslint/eslint-plugin": "^5.5.0", + "@typescript-eslint/parser": "^5.5.0", + "babel-preset-react-app": "^10.0.1", + "confusing-browser-globals": "^1.0.11", + "eslint-plugin-flowtype": "^8.0.3", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jest": "^25.3.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.27.1", + "eslint-plugin-react-hooks": "^4.3.0", + "eslint-plugin-testing-library": "^5.0.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "eslint": "^8.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "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" + } + }, + "node_modules/eslint-import-resolver-node/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/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "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" + } + }, + "node_modules/eslint-module-utils/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/eslint-plugin-flowtype": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", + "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", + "license": "BSD-3-Clause", + "dependencies": { + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@babel/plugin-syntax-flow": "^7.14.5", + "@babel/plugin-transform-react-jsx": "^7.14.9", + "eslint": "^8.1.0" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "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" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/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/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jest": { + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", + "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^4.0.0 || ^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.1.0", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-testing-library": { + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.11.1.tgz", + "integrity": "sha512-5eX9e1Kc2PqVRed3taaLnAAqPZGEX75C+M/rXzUAI3wIg/ZxzUm1OVAwfe/O+vE+6YXOLetSe9g5GKD2ecXipw==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^5.58.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0", + "npm": ">=6" + }, + "peerDependencies": { + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "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==", + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz", + "integrity": "sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==", + "license": "MIT", + "dependencies": { + "@types/eslint": "^7.29.0 || ^8.4.1", + "jest-worker": "^28.0.2", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0", + "webpack": "^5.0.0" + } + }, + "node_modules/eslint-webpack-plugin/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": ">=8" + } + }, + "node_modules/eslint-webpack-plugin/node_modules/jest-worker": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", + "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/eslint-webpack-plugin/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==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/eslint/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/eslint/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/eslint/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": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "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": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "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==", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "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/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "license": "MIT" + }, + "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/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/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/events": { + "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/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "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": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dependencies": { + "@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/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "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.10.0" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/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/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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "license": "Apache-2.0", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "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==", + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==" + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/file-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/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/filelist/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/filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 0.4.0" + } + }, + "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==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "license": "MIT", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "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/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", + "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=10", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "eslint": ">= 6", + "typescript": ">= 2.7", + "vue-template-compiler": "*", + "webpack": ">= 4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/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/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/form-data": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.2.tgz", + "integrity": "sha512-sJe+TQb2vIaIyO783qN6BlMYWMw3WBOHA1Ay2qxsnjuafEOQFJ2JakedOQirT6D5XPRxDvS7AHYyem9fTpb4LQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formik": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.6.tgz", + "integrity": "sha512-A+2EI7U7aG296q2TLGvNapDNTZp1khVt5Vk0Q/fyfSROss0V/V6+txt2aJnwEos44IxTCW/LYAi/zgWzlevj+g==", + "funding": [ + { + "type": "individual", + "url": "https://opencollective.com/formik" + } + ], + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.1", + "deepmerge": "^2.1.1", + "hoist-non-react-statics": "^3.3.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-fast-compare": "^2.0.1", + "tiny-warning": "^1.0.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/formik-material-ui": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/formik-material-ui/-/formik-material-ui-3.0.1.tgz", + "integrity": "sha512-N8oxZIdhY70npRv86IfF6Zaaps9RL3a37XRdq02WDroB3XZC1mXs6lA/zQ09ZYFWYJp/UjI80SKVpVa/xJOJJA==", + "peerDependencies": { + "@material-ui/core": ">=4.0.0", + "formik": ">=2.0.0", + "react": ">=16.8.0", + "tiny-warning": ">=1.0.2" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "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_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "license": "Unlicense" + }, + "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, + "optional": true, + "os": [ + "darwin" + ], + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "license": "ISC" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "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==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause" + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "license": "MIT", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "license": "MIT", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globalize": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/globalize/-/globalize-0.1.1.tgz", + "integrity": "sha512-5e01v8eLGfuQSOvx2MsDMOWS0GFtCx1wPzQSmcHw4hkxFzrQDBO3Xwg/m8Hr/7qXMrHeOIE29qWVzyv06u1TZA==" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gn-api-sdk-node": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/gn-api-sdk-node/-/gn-api-sdk-node-3.0.4.tgz", + "integrity": "sha512-DZKeTj9bw+Ybe2ZZG9oeWlOEPUm3wsSpLnr/ZAEhxR2Q+b4xZ9juo0tblvc2qi6Q+hnEs03LOR+ULr+kt8mYkQ==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dependencies": { + "axios": "^1.2.1", + "randomstring": "^1.2.2" + } + }, + "node_modules/gn-api-sdk-node/node_modules/axios": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/gn-api-sdk-node/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gn-api-sdk-node/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==" + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "license": "MIT" + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "license": "MIT", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "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": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "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==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "dependencies": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "node_modules/history/node_modules/resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, + "node_modules/history/node_modules/value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/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==" + }, + "node_modules/hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/howler": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/howler/-/howler-2.2.4.tgz", + "integrity": "sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==" + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/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/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/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/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^1.0.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "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==", + "license": "MIT" + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz", + "integrity": "sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==", + "license": "MIT", + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/html2pdf.js": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/html2pdf.js/-/html2pdf.js-0.10.2.tgz", + "integrity": "sha512-WyHVeMb18Bp7vYTmBv1GVsThH//K7SRfHdSdhHPkl4JvyQarNQXnailkYn0QUbRRmnN5rdbbmSIGEsPZtzPy2Q==", + "dependencies": { + "es6-promise": "^4.2.5", + "html2canvas": "^1.0.0", + "jspdf": "^2.3.1" + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "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==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/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==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "license": "MIT" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-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": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": 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/http-proxy-middleware": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", + "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", + "license": "MIT", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-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": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "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==", + "license": "MIT" + }, + "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==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/i18next": { + "version": "19.9.2", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-19.9.2.tgz", + "integrity": "sha512-0i6cuo6ER6usEOtKajUUDj92zlG+KArFia0857xxiEHAQcUwh/RtOQocui1LPJwunSYT574Pk64aNva1kwtxZg==", + "dependencies": { + "@babel/runtime": "^7.12.0" + } + }, + "node_modules/i18next-browser-languagedetector": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.8.tgz", + "integrity": "sha512-Svm+MduCElO0Meqpj1kJAriTC6OhI41VhlT/A0UPjGoPZBhAHIaGE5EfsHlTpgdH09UVX7rcc72pSDDBeKSQQA==", + "dependencies": { + "@babel/runtime": "^7.19.0" + } + }, + "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/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", + "license": "ISC" + }, + "node_modules/identity-obj-proxy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", + "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "dependencies": { + "harmony-reflect": "^1.4.6" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/identity-obj-proxy/node_modules/harmony-reflect": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", + "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/immutability-helper": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/immutability-helper/-/immutability-helper-2.9.1.tgz", + "integrity": "sha512-r/RmRG8xO06s/k+PIaif2r5rGc3j4Yhc01jSBfwPCXDLYZwp/yxralI37Df1mwmuzcCsen/E/ITKcTEvc1PQmQ==", + "dependencies": { + "invariant": "^2.2.0" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/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==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "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": { + "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/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-blob": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-blob/-/is-blob-2.1.0.tgz", + "integrity": "sha512-SZ/fTft5eUhQM6oF/ZaASFDEdbFVe89Imltn9uZr03wdKMcWNVYSMjQPFtg05QuNkt5l5c135ElvXEQG0rk4tw==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "license": "MIT", + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "license": "MIT" + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "license": "MIT" + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "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/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/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==", + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/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/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==", + "license": "MIT" + }, + "node_modules/istanbul-lib-source-maps/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/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "license": "MIT", + "dependencies": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-circus/node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "license": "MIT", + "dependencies": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-cli/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-cli/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-config/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-config/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/jest-config/node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-config/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-config/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-config/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dependencies": { + "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/jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-each/node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-environment-jsdom/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-environment-node/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-haste-map/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-haste-map/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-haste-map/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-jasmine2/node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "license": "MIT", + "dependencies": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-leak-detector/node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-leak-detector/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-leak-detector/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "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==", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "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==", + "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" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-mock/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-mock/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-resolve/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-resolve/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "license": "MIT", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-runner/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-runtime/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-snapshot/node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "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==", + "dependencies": { + "@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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-validate/node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/jest-watch-typeahead": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", + "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.3.1", + "chalk": "^4.0.0", + "jest-regex-util": "^28.0.0", + "jest-watcher": "^28.0.0", + "slash": "^4.0.0", + "string-length": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "jest": "^27.0.0 || ^28.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/console": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/console/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/test-result": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", + "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", + "license": "MIT", + "dependencies": { + "@jest/console": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^28.1.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": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", + "license": "MIT" + }, + "node_modules/jest-watch-typeahead/node_modules/emittery": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", + "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-message-util/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "license": "MIT", + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", + "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", + "license": "MIT", + "dependencies": { + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "jest-util": "^28.1.3", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher/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==", + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher/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/jest-watch-typeahead/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "license": "MIT", + "dependencies": { + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/string-length/node_modules/char-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", + "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/jest-watch-typeahead/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "license": "MIT", + "dependencies": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-watcher/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-watcher/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-watcher/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "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==" + }, + "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==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "license": "MIT", + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "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==", + "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==", + "license": "MIT" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "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==", + "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==", + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonpath": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz", + "integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==", + "license": "MIT", + "dependencies": { + "esprima": "1.2.2", + "static-eval": "2.0.2", + "underscore": "1.12.1" + } + }, + "node_modules/jsonpath/node_modules/esprima": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", + "integrity": "sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/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==" + }, + "node_modules/jspdf": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.2.tgz", + "integrity": "sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==", + "dependencies": { + "@babel/runtime": "^7.23.2", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "fflate": "^0.8.1" + }, + "optionalDependencies": { + "canvg": "^3.0.6", + "core-js": "^3.6.0", + "dompurify": "^2.5.4", + "html2canvas": "^1.0.0-rc.5" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws/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/jws/node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws/node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/lamejs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/lamejs/-/lamejs-1.2.1.tgz", + "integrity": "sha512-s7bxvjvYthw6oPLCm5pFxvA84wUROODB8jEO2+CE1adhKgrIvVOlmMgY8zyugxGrvRaDHNJanOiS21/emty6dQ==", + "dependencies": { + "use-strict": "1.0.1" + } + }, + "node_modules/lamejs/node_modules/use-strict": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/use-strict/-/use-strict-1.0.1.tgz", + "integrity": "sha512-IeiWvvEXfW5ltKVMkxq6FvNf2LojMKvB2OCeja6+ct24S1XOmQw2dGr2JyndwACWAGJva9B7yPHwAmeA9QCqAQ==" + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/launch-editor": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", + "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", + "license": "MIT", + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "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==", + "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==", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "license": "MIT", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "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/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "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==", + "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==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "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==", + "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==" + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "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/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==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/luxon": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", + "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "license": "MIT", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/markdown-to-jsx": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.4.7.tgz", + "integrity": "sha512-0+ls1IQZdU6cwM1yu0ZjjiVWYtkbExSyUIFU2ZeDIFuZM1W42Mh4OlJ4nb4apX4H8smxDHRdFaoIVJGwfv5hkg==", + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, + "node_modules/match-sorter": { + "version": "6.3.4", + "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.4.tgz", + "integrity": "sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==", + "dependencies": { + "@babel/runtime": "^7.23.8", + "remove-accents": "0.5.0" + } + }, + "node_modules/match-sorter/node_modules/remove-accents": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", + "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==" + }, + "node_modules/material-colors": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", + "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" + }, + "node_modules/material-ui-color": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/material-ui-color/-/material-ui-color-1.2.0.tgz", + "integrity": "sha512-bD2Rww+hakJxD2/19uxc280Vh292DnRStLke2LDFavVtGd5fzOz09zIrHO3ZHlMkJFsvwx6IwiB4/932ftv0sQ==", + "peerDependencies": { + "@material-ui/core": "^4.9.5", + "material-ui-popup-state": "^1.5.3", + "prop-types": "^15.7.2", + "react": "^16.0.0 || ^17.0.0", + "react-dom": "^16.0.0 || ^17.0.0" + } + }, + "node_modules/material-ui-nested-menu-item": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/material-ui-nested-menu-item/-/material-ui-nested-menu-item-1.0.2.tgz", + "integrity": "sha512-LZb8xI0FrAI/A3P2vT3CB9bmSoOFWOK0dikTc1t9VvEpp1a8hZkbVUz7VhETnoLUYu3NXCkgulmXcl3zitqI9A==", + "peerDependencies": { + "@material-ui/core": "^4.9.0", + "@material-ui/icons": "^4.5.1", + "clsx": "^1.0.4", + "react": ">=16.9.0" + } + }, + "node_modules/material-ui-popup-state": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/material-ui-popup-state/-/material-ui-popup-state-1.9.3.tgz", + "integrity": "sha512-+Ete5Tzw5rXlYfmqptOS8kBUH8vnK5OJsd6IQ7SHtLjU0PsvsmM73M/k8ot0xkX4RmPGuNRsFbK3mlCe/ClQuw==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@material-ui/types": "^6.0.1", + "classnames": "^2.2.6", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "@material-ui/core": "^4.0.0 || ^5.0.0-beta", + "react": "^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/material-ui-popup-state/node_modules/@material-ui/types": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-6.0.2.tgz", + "integrity": "sha512-/XUca4wUb9pWimLLdM1PE8KS8rTbDEGohSGkGtk3WST7lm23m+8RYv9uOmrvOg/VSsl4bMiOv4t2/LCb+RLbTg==", + "peer": true, + "peerDependencies": { + "@types/react": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "license": "CC0-1.0" + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "license": "Unlicense", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "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==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mic-recorder-to-mp3": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/mic-recorder-to-mp3/-/mic-recorder-to-mp3-2.2.2.tgz", + "integrity": "sha512-xDkOaHbojW3bdKOGn9CI5dT+Mc0RrfczsX/Y1zGJp3FUB4zei5ZKFnNm7Nguc9v910wkd7T3csnCTq5EtCF3Zw==", + "dependencies": { + "lamejs": "^1.2.0" + }, + "peerDependencies": { + "webrtc-adapter": ">=4.1.1" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "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" + } + }, + "node_modules/mime-types": { + "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" + }, + "engines": { + "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==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", + "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", + "license": "MIT", + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, + "node_modules/minimatch": { + "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" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "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/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "license": "MIT", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoclone": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", + "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "license": "MIT" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "license": "MIT" + }, + "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/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", + "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" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.8.tgz", + "integrity": "sha512-qkHIGe4q0lSYMv0XI4SsBTJz3WaURhLvd0lKSgtVuOsJ2krg4SgMw3PIRQFMp07yi++UR3se2mkcLqsBNpBb/A==", + "license": "MIT", + "dependencies": { + "array.prototype.reduce": "^1.0.6", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "gopd": "^1.0.1", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "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==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-finished/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/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "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==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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/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/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "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/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "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/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "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" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/popper.js": { + "version": "1.16.1-lts", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz", + "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==" + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", + "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-browser-comments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", + "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", + "license": "CC0-1.0", + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "browserslist": ">=4", + "postcss": ">=8" + } + }, + "node_modules/postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=7.6.0" + }, + "peerDependencies": { + "postcss": "^8.4.6" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", + "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", + "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", + "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-custom-media": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", + "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-custom-properties": { + "version": "12.1.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz", + "integrity": "sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-custom-selectors": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", + "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-dir-pseudo-class": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", + "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", + "license": "CC0-1.0", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "license": "MIT", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "license": "MIT", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "license": "MIT", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "license": "MIT", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", + "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", + "license": "CC0-1.0", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-env-function": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", + "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-flexbugs-fixes": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", + "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8.1.4" + } + }, + "node_modules/postcss-focus-visible": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", + "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", + "license": "CC0-1.0", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-within": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", + "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", + "license": "CC0-1.0", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", + "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", + "license": "CC0-1.0", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-image-set-function": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", + "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-initial": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-lab-function": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", + "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", + "license": "CC0-1.0", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/postcss-load-config/node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "license": "MIT", + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-logical": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", + "license": "CC0-1.0", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-media-minmax": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "license": "MIT", + "dependencies": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "license": "ISC", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nesting": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", + "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", + "license": "CC0-1.0", + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-normalize": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-10.0.1.tgz", + "integrity": "sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==", + "license": "CC0-1.0", + "dependencies": { + "@csstools/normalize.css": "*", + "postcss-browser-comments": "^4", + "sanitize.css": "*" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "browserslist": ">= 4", + "postcss": ">= 8" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "license": "MIT", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "license": "MIT", + "dependencies": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-opacity-percentage": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", + "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", + "funding": [ + { + "type": "kofi", + "url": "https://ko-fi.com/mrcgrtz" + }, + { + "type": "liberapay", + "url": "https://liberapay.com/mrcgrtz" + } + ], + "license": "MIT", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "license": "MIT", + "dependencies": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-overflow-shorthand": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", + "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-place": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", + "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-preset-env": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz", + "integrity": "sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==", + "license": "CC0-1.0", + "dependencies": { + "@csstools/postcss-cascade-layers": "^1.1.1", + "@csstools/postcss-color-function": "^1.1.1", + "@csstools/postcss-font-format-keywords": "^1.0.1", + "@csstools/postcss-hwb-function": "^1.0.2", + "@csstools/postcss-ic-unit": "^1.0.1", + "@csstools/postcss-is-pseudo-class": "^2.0.7", + "@csstools/postcss-nested-calc": "^1.0.0", + "@csstools/postcss-normalize-display-values": "^1.0.1", + "@csstools/postcss-oklab-function": "^1.1.1", + "@csstools/postcss-progressive-custom-properties": "^1.3.0", + "@csstools/postcss-stepped-value-functions": "^1.0.1", + "@csstools/postcss-text-decoration-shorthand": "^1.0.0", + "@csstools/postcss-trigonometric-functions": "^1.0.2", + "@csstools/postcss-unset-value": "^1.0.2", + "autoprefixer": "^10.4.13", + "browserslist": "^4.21.4", + "css-blank-pseudo": "^3.0.3", + "css-has-pseudo": "^3.0.4", + "css-prefers-color-scheme": "^6.0.3", + "cssdb": "^7.1.0", + "postcss-attribute-case-insensitive": "^5.0.2", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^4.2.4", + "postcss-color-hex-alpha": "^8.0.4", + "postcss-color-rebeccapurple": "^7.1.1", + "postcss-custom-media": "^8.0.2", + "postcss-custom-properties": "^12.1.10", + "postcss-custom-selectors": "^6.0.3", + "postcss-dir-pseudo-class": "^6.0.5", + "postcss-double-position-gradients": "^3.1.2", + "postcss-env-function": "^4.0.6", + "postcss-focus-visible": "^6.0.4", + "postcss-focus-within": "^5.0.4", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^3.0.5", + "postcss-image-set-function": "^4.0.7", + "postcss-initial": "^4.0.1", + "postcss-lab-function": "^4.2.1", + "postcss-logical": "^5.0.4", + "postcss-media-minmax": "^5.0.0", + "postcss-nesting": "^10.2.0", + "postcss-opacity-percentage": "^1.1.2", + "postcss-overflow-shorthand": "^3.0.4", + "postcss-page-break": "^3.0.4", + "postcss-place": "^7.0.5", + "postcss-pseudo-class-any-link": "^7.1.6", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", + "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", + "license": "CC0-1.0", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8.0.3" + } + }, + "node_modules/postcss-selector-not": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", + "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/postcss-svgo/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/postcss-svgo/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "license": "CC0-1.0" + }, + "node_modules/postcss-svgo/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/postcss-svgo/node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "license": "MIT", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.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==", + "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/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==", + "license": "MIT" + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "license": "MIT", + "dependencies": { + "asap": "~2.0.6" + } + }, + "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==", + "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==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "dependencies": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "peerDependencies": { + "react": ">=0.14.0" + } + }, + "node_modules/prop-types-extra/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==" + }, + "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==" + }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==" + }, + "node_modules/proxy-addr": { + "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==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/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/proxy-addr/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==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", + "license": "MIT", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qr.js": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", + "integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==" + }, + "node_modules/qrcode.react": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-1.0.1.tgz", + "integrity": "sha512-8d3Tackk8IRLXTo67Y+c1rpaiXjoz/Dd2HpcMdW//62/x8J1Nbho14Kh8x974t9prsLHN6XqVgcnRiBGFptQmg==", + "dependencies": { + "loose-envify": "^1.4.0", + "prop-types": "^15.6.0", + "qr.js": "0.0.0" + }, + "peerDependencies": { + "react": "^15.5.3 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "dependencies": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "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/raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "dependencies": { + "performance-now": "^2.1.0" + } + }, + "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" + } + }, + "node_modules/randomstring": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/randomstring/-/randomstring-1.3.0.tgz", + "integrity": "sha512-gY7aQ4i1BgwZ8I1Op4YseITAyiDiajeZOPQUbIq9TPGPhUm5FX59izIaOpmKbME1nmnEiABf28d9K2VSii6BBg==", + "dependencies": { + "randombytes": "2.0.3" + }, + "bin": { + "randomstring": "bin/randomstring" + }, + "engines": { + "node": "*" + } + }, + "node_modules/randomstring/node_modules/randombytes": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.3.tgz", + "integrity": "sha512-lDVjxQQFoCG1jcrP06LNo2lbWp4QTShEXnhActFBwYuHprllQV6VUpwreApsYqCgD+N1mHoqJ/BI/4eV4R2GYg==" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-app-polyfill": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", + "integrity": "sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==", + "license": "MIT", + "dependencies": { + "core-js": "^3.19.2", + "object-assign": "^4.1.1", + "promise": "^8.1.0", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.9", + "whatwg-fetch": "^3.6.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-big-calendar": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-1.13.2.tgz", + "integrity": "sha512-yzeVRM1I+JloeJXytrZx2lJWKUfLAi5bsgGuBjh3aFSHZrdFcGnfA7LE6pBacdyOG+NGP+332m2MziszkmQWcw==", + "dependencies": { + "@babel/runtime": "^7.20.7", + "clsx": "^1.2.1", + "date-arithmetic": "^4.1.0", + "dayjs": "^1.11.7", + "dom-helpers": "^5.2.1", + "globalize": "^0.1.1", + "invariant": "^2.2.4", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "luxon": "^3.2.1", + "memoize-one": "^6.0.0", + "moment": "^2.29.4", + "moment-timezone": "^0.5.40", + "prop-types": "^15.8.1", + "react-overlays": "^5.2.1", + "uncontrollable": "^7.2.1" + }, + "peerDependencies": { + "react": "^16.14.0 || ^17 || ^18", + "react-dom": "^16.14.0 || ^17 || ^18" + } + }, + "node_modules/react-bootstrap": { + "version": "2.10.4", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.4.tgz", + "integrity": "sha512-W3398nBM2CBfmGP2evneEO3ZZwEMPtHs72q++eNw60uDGDAdiGn0f9yNys91eo7/y8CTF5Ke1C0QO8JFVPU40Q==", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@restart/hooks": "^0.4.9", + "@restart/ui": "^1.6.9", + "@types/react-transition-group": "^4.4.6", + "classnames": "^2.3.2", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.5", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "@types/react": ">=16.14.8", + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-chartjs-2": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-4.3.1.tgz", + "integrity": "sha512-5i3mjP6tU7QSn0jvb8I4hudTzHJqS8l00ORJnVwI2sYu0ihpj83Lv2YzfxunfxTZkscKvZu2F2w9LkwNBhj6xA==", + "peerDependencies": { + "chart.js": "^3.5.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-color": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz", + "integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==", + "dependencies": { + "@icons/material": "^0.2.4", + "lodash": "^4.17.15", + "lodash-es": "^4.17.15", + "material-colors": "^1.2.1", + "prop-types": "^15.5.10", + "reactcss": "^1.2.0", + "tinycolor2": "^1.4.1" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-copy-to-clipboard": { + "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==", + "dependencies": { + "copy-to-clipboard": "^3.3.1", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": "^15.3.0 || 16 || 17 || 18" + } + }, + "node_modules/react-csv": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/react-csv/-/react-csv-2.2.2.tgz", + "integrity": "sha512-RG5hOcZKZFigIGE8LxIEV/OgS1vigFQT4EkaHeKgyuCbUAu9Nbd/1RYq++bJcJJ9VOqO/n9TZRADsXNDR4VEpw==" + }, + "node_modules/react-currency-format": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/react-currency-format/-/react-currency-format-1.1.0.tgz", + "integrity": "sha512-WWrEOIp/3GbDSk1wlhFXaBc7IHGT3IwL306DHbGP3GVr4YFa0iS5hHPbKjHa0haruGL4Ly+WG4/5jBHpUtgqZg==", + "dependencies": { + "prop-types": "^15.6.0" + }, + "peerDependencies": { + "react": "^0.14 || ^15.0.0-rc || ^15.0.0 || ^16.0.0-rc || ^16.0.0 || ^17.0.0", + "react-dom": "^0.14 || ^15.0.0-rc || ^15.0.0 || ^16.0.0-rc || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-dev-utils/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": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/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==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/react-dev-utils/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==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + }, + "peerDependencies": { + "react": "17.0.2" + } + }, + "node_modules/react-dom/node_modules/scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==", + "license": "MIT" + }, + "node_modules/react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" + }, + "node_modules/react-feather": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/react-feather/-/react-feather-2.0.10.tgz", + "integrity": "sha512-BLhukwJ+Z92Nmdcs+EMw6dy1Z/VLiJTzEQACDUEnWMClhYnFykJCGWQx+NmwP/qQHGX/5CzQ+TGi8ofg2+HzVQ==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": ">=16.8.6" + } + }, + "node_modules/react-icons": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz", + "integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-input-mask": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-input-mask/-/react-input-mask-2.0.4.tgz", + "integrity": "sha512-1hwzMr/aO9tXfiroiVCx5EtKohKwLk/NT8QlJXHQ4N+yJJFyUuMT+zfTpLBwX/lK3PkuMlievIffncpMZ3HGRQ==", + "dependencies": { + "invariant": "^2.2.4", + "warning": "^4.0.2" + }, + "peerDependencies": { + "react": ">=0.14.0", + "react-dom": ">=0.14.0" + } + }, + "node_modules/react-is": { + "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==" + }, + "node_modules/react-jwt": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/react-jwt/-/react-jwt-1.2.2.tgz", + "integrity": "sha512-1I0Ei1F9m7Nzo1jaeeZk7dpUC4srIVC3bUxDqgD9mFltoTyytp5TFPkK3XMWfLE5iYUsQ+C7tNYbf/gd61D4Sw==", + "engines": { + "node": ">=10" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-modal-image": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-modal-image/-/react-modal-image-2.6.0.tgz", + "integrity": "sha512-NNc1xPKzFAn0VsNMdJ8NXt6c54aL/z0fcoYmw9qn4SBUONdGl+8LOQ0sTfo0wtdzcjLiby/ncloHcAL+UI+wIA==" + }, + "node_modules/react-number-format": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-4.9.4.tgz", + "integrity": "sha512-Gq20Z3ugqPLFgeaidnx5on9cNpbQZntPN3QgNAL/WJrNNlQnNznY0LCx7g8xtssmRBw0/hw+SCqw6zAcajooiA==", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-overlays": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.2.1.tgz", + "integrity": "sha512-GLLSOLWr21CqtJn8geSwQfoJufdt3mfdsnIiQswouuQ2MMPns+ihZklxvsTDKD3cR2tF8ELbi5xUsvqVhR6WvA==", + "dependencies": { + "@babel/runtime": "^7.13.8", + "@popperjs/core": "^2.11.6", + "@restart/hooks": "^0.4.7", + "@types/warning": "^3.0.0", + "dom-helpers": "^5.2.0", + "prop-types": "^15.7.2", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.3.0", + "react-dom": ">=16.3.0" + } + }, + "node_modules/react-overlays/node_modules/@types/warning": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz", + "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==" + }, + "node_modules/react-popopo": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/react-popopo/-/react-popopo-2.1.9.tgz", + "integrity": "sha512-zXOpcLSpaLZmBxhdtenJzQPLjY81XknVS/tXH4Kv5BBrnYIUPHvVdGmS7+o9s7DjCzzdK7AdVwtG+FVSO0cZ8g==", + "dependencies": { + "classnames": ">= 2.0", + "prop-types": "^15.7.2", + "react": ">= 16.3", + "react-dom": ">= 16.3", + "styled-components": ">= 4.0" + }, + "peerDependencies": { + "classnames": ">= 2.0", + "react": ">= 16.3", + "react-dom": ">= 16.3", + "styled-components": ">= 4.0" + } + }, + "node_modules/react-qr-code": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.0.15.tgz", + "integrity": "sha512-MkZcjEXqVKqXEIMVE0mbcGgDpkfSdd8zhuzXEl9QzYeNcw8Hq2oVIzDLWuZN2PQBwM5PWjc2S31K8Q1UbcFMfw==", + "dependencies": { + "prop-types": "^15.8.1", + "qr.js": "0.0.0" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-query": { + "version": "3.39.3", + "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", + "integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "broadcast-channel": "^3.4.1", + "match-sorter": "^6.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/react-refresh": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", + "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", + "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-router-dom": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", + "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.3.4", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-router/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/react-router/node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/react-router/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==" + }, + "node_modules/react-scripts": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", + "integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.16.0", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", + "@svgr/webpack": "^5.5.0", + "babel-jest": "^27.4.2", + "babel-loader": "^8.2.3", + "babel-plugin-named-asset-import": "^0.3.8", + "babel-preset-react-app": "^10.0.1", + "bfj": "^7.0.2", + "browserslist": "^4.18.1", + "camelcase": "^6.2.1", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "css-loader": "^6.5.1", + "css-minimizer-webpack-plugin": "^3.2.0", + "dotenv": "^10.0.0", + "dotenv-expand": "^5.1.0", + "eslint": "^8.3.0", + "eslint-config-react-app": "^7.0.1", + "eslint-webpack-plugin": "^3.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^10.0.0", + "html-webpack-plugin": "^5.5.0", + "identity-obj-proxy": "^3.0.0", + "jest": "^27.4.3", + "jest-resolve": "^27.4.2", + "jest-watch-typeahead": "^1.0.0", + "mini-css-extract-plugin": "^2.4.5", + "postcss": "^8.4.4", + "postcss-flexbugs-fixes": "^5.0.2", + "postcss-loader": "^6.2.1", + "postcss-normalize": "^10.0.1", + "postcss-preset-env": "^7.0.1", + "prompts": "^2.4.2", + "react-app-polyfill": "^3.0.0", + "react-dev-utils": "^12.0.1", + "react-refresh": "^0.11.0", + "resolve": "^1.20.0", + "resolve-url-loader": "^4.0.0", + "sass-loader": "^12.3.0", + "semver": "^7.3.5", + "source-map-loader": "^3.0.0", + "style-loader": "^3.3.1", + "tailwindcss": "^3.0.2", + "terser-webpack-plugin": "^5.2.5", + "webpack": "^5.64.4", + "webpack-dev-server": "^4.6.0", + "webpack-manifest-plugin": "^4.0.2", + "workbox-webpack-plugin": "^6.4.1" + }, + "bin": { + "react-scripts": "bin/react-scripts.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + }, + "peerDependencies": { + "react": ">= 16", + "typescript": "^3.2.1 || ^4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/react-smooth": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.1.tgz", + "integrity": "sha512-OE4hm7XqR0jNOq3Qmk9mFLyd6p2+j6bvbPJ7qlB7+oo0eNcL2l7WQzG6MBnT3EXY6xzkLMUBec3AfewJdA0J8w==", + "dependencies": { + "fast-equals": "^5.0.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-smooth/node_modules/fast-equals": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", + "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/react-text-mask": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-text-mask/-/react-text-mask-5.5.0.tgz", + "integrity": "sha512-SLJlJQxa0uonMXsnXRpv5abIepGmHz77ylQcra0GNd7Jtk4Wj2Mtp85uGQHv1avba2uI8ZvRpIEQPpJKsqRGYw==", + "dependencies": { + "prop-types": "^15.5.6" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-to-print": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/react-to-print/-/react-to-print-3.0.2.tgz", + "integrity": "sha512-FS/Z4LLq0bgWaxd7obygFQ8yRFdKW74iE8fIVjFFsPJWIXmuL8CIO+4me1Hj44lrlxQ00gscSNb3BRM8olbwXg==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ~19" + } + }, + "node_modules/react-toastify": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.0.0.tgz", + "integrity": "sha512-gmxAFTKV0VVN7s5UEcZdC+bBR1EQtsqXgHJWQgB0G5J8m3Mdxz1Pacm7BJ1nTHkMMNfupruKCu7wUwAq46Z1jg==", + "license": "MIT", + "dependencies": { + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/react-trello": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/react-trello/-/react-trello-2.2.11.tgz", + "integrity": "sha512-Zm7qrPAcFTysUXK6wpa1KhTt7fTadIZgNGYj+blDWGnppFYW7GMi1p+S6J8P9quhzKnIJTSZXVzHA1f4sREIVQ==", + "dependencies": { + "autosize": "^4.0.2", + "classnames": "^2.2.6", + "immutability-helper": "^2.8.1", + "lodash": "^4.17.11", + "prop-types": "^15.7.2", + "react-popopo": "^2.1.9", + "react-redux": "^5.0.7", + "redux": "^4.0.0", + "redux-actions": "^2.6.1", + "redux-logger": "^3.0.6", + "trello-smooth-dnd": "1.0.0", + "uuid": "^3.3.2" + }, + "peerDependencies": { + "lodash": ">= 4.17.11", + "react": "*", + "react-dom": "*", + "react-redux": ">= 5.0.7", + "redux": ">= 4.0.0", + "redux-actions": ">= 2.6.1", + "redux-logger": ">= 3.0.6", + "styled-components": ">= 4.0.3" + } + }, + "node_modules/react-trello/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==" + }, + "node_modules/react-trello/node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "node_modules/react-trello/node_modules/react-redux": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.1.2.tgz", + "integrity": "sha512-Ns1G0XXc8hDyH/OcBHOxNgQx9ayH3SPxBnFCOidGKSle8pKihysQw2rG/PmciUQRoclhVBO8HMhiRmGXnDja9Q==", + "dependencies": { + "@babel/runtime": "^7.1.2", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4", + "loose-envify": "^1.1.0", + "prop-types": "^15.6.1", + "react-is": "^16.6.0", + "react-lifecycles-compat": "^3.0.0" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.0-0 || ^16.0.0-0", + "redux": "^2.0.0 || ^3.0.0 || ^4.0.0-0" + } + }, + "node_modules/react-trello/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/reactcss": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", + "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==", + "dependencies": { + "lodash": "^4.0.1" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recharts": { + "version": "2.12.7", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.12.7.tgz", + "integrity": "sha512-hlLJMhPQfv4/3NBSAyq3gzGg4h2v69RJh6KU7b3pXYNNAELs9kEoXOjbkxdXpALqKBoVmVptGfLpxdaVYqjmXQ==", + "dependencies": { + "clsx": "^2.0.0", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.21", + "react-is": "^16.10.2", + "react-smooth": "^4.0.0", + "recharts-scale": "^0.4.4", + "tiny-invariant": "^1.3.1", + "victory-vendor": "^36.6.8" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "dependencies": { + "decimal.js-light": "^2.4.1" + } + }, + "node_modules/recharts-scale/node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" + }, + "node_modules/recharts/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/recharts/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==" + }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "license": "MIT", + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redent/node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/redent/node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/redent/node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/redux-actions": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/redux-actions/-/redux-actions-2.6.5.tgz", + "integrity": "sha512-pFhEcWFTYNk7DhQgxMGnbsB1H2glqhQJRQrtPb96kD3hWiZRzXHwwmFPswg6V2MjraXRXWNmuP9P84tvdLAJmw==", + "dependencies": { + "invariant": "^2.2.4", + "just-curry-it": "^3.1.0", + "loose-envify": "^1.4.0", + "reduce-reducers": "^0.4.3", + "to-camel-case": "^1.0.0" + } + }, + "node_modules/redux-actions/node_modules/just-curry-it": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/just-curry-it/-/just-curry-it-3.2.1.tgz", + "integrity": "sha512-Q8206k8pTY7krW32cdmPsP+DqqLgWx/hYPSj9/+7SYqSqz7UuwPbfSe07lQtvuuaVyiSJveXk0E5RydOuWwsEg==" + }, + "node_modules/redux-actions/node_modules/reduce-reducers": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/reduce-reducers/-/reduce-reducers-0.4.3.tgz", + "integrity": "sha512-+CNMnI8QhgVMtAt54uQs3kUxC3Sybpa7Y63HR14uGLgI9/QR5ggHvpxwhGGe3wmx5V91YwqQIblN9k5lspAmGw==" + }, + "node_modules/redux-actions/node_modules/to-camel-case": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-camel-case/-/to-camel-case-1.0.0.tgz", + "integrity": "sha512-nD8pQi5H34kyu1QDMFjzEIYqk0xa9Alt6ZfrdEMuHCFOfTLhDG5pgTu/aAM9Wt9lXILwlXmWP43b8sav0GNE8Q==", + "dependencies": { + "to-space-case": "^1.0.0" + } + }, + "node_modules/redux-actions/node_modules/to-no-case": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz", + "integrity": "sha512-Z3g735FxuZY8rodxV4gH7LxClE4H0hTIyHNIHdk+vpQxjLm0cwnKXq/OFVZ76SOQmto7txVcwSCwkU5kqp+FKg==" + }, + "node_modules/redux-actions/node_modules/to-space-case": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz", + "integrity": "sha512-rLdvwXZ39VOn1IxGL3V6ZstoTbwLRckQmn/U8ZDLuWwIXNpuZDhQ3AiRUlhTbOXFVE9C+dR51wM0CBDhk31VcA==", + "dependencies": { + "to-no-case": "^1.0.0" + } + }, + "node_modules/redux-logger": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-3.0.6.tgz", + "integrity": "sha512-JoCIok7bg/XpqA1JqCqXFypuqBbQzGQySrhFzewB7ThcnysTO30l4VCst86AuB9T9tuT03MAA56Jw2PNhRSNCg==", + "dependencies": { + "deep-diff": "^0.3.5" + } + }, + "node_modules/redux-logger/node_modules/deep-diff": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz", + "integrity": "sha512-yVn6RZmHiGnxRKR9sJb3iVV2XTF1Ghh2DiWRZ3dMnGc43yUdWWF/kX6lQyk3+P84iprfWKU/8zFTrlkvtFm1ug==" + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz", + "integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==", + "license": "MIT" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", + "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.11.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.2.tgz", + "integrity": "sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA==", + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.0.2" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "license": "MIT", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "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-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "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==", + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-url-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", + "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", + "license": "MIT", + "dependencies": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^7.0.35", + "source-map": "0.6.1" + }, + "engines": { + "node": ">=8.9" + }, + "peerDependencies": { + "rework": "1.0.1", + "rework-visit": "1.0.0" + }, + "peerDependenciesMeta": { + "rework": { + "optional": true + }, + "rework-visit": { + "optional": true + } + } + }, + "node_modules/resolve-url-loader/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/resolve-url-loader/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "license": "ISC" + }, + "node_modules/resolve-url-loader/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/resolve-url-loader/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/resolve.exports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", + "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "optional": true, + "engines": { + "node": ">= 0.8.15" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "2.79.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", + "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", + "license": "MIT", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } + }, + "node_modules/rollup-plugin-terser/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": ">=8" + } + }, + "node_modules/rollup-plugin-terser/node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/rollup-plugin-terser/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/rollup-plugin-terser/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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "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": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sanitize.css": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", + "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==", + "license": "CC0-1.0" + }, + "node_modules/sass-loader": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", + "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", + "license": "MIT", + "dependencies": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "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/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "license": "MIT" + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "license": "MIT", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "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==" + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "license": "ISC" + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "license": "ISC" + }, + "node_modules/serve-index/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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "ISC" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/socket.io-client": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz", + "integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-client/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-client/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "license": "MIT", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "license": "MIT" + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", + "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", + "license": "MIT", + "dependencies": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.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==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/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/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", + "license": "MIT" + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/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/spdy-transport/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/spdy/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/spdy/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/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/ssf": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", + "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", + "dependencies": { + "frac": "~1.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ssf/node_modules/frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", + "license": "MIT" + }, + "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==", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stackblur-canvas": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", + "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "license": "MIT" + }, + "node_modules/static-eval": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", + "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", + "license": "MIT", + "dependencies": { + "escodegen": "^1.8.1" + } + }, + "node_modules/static-eval/node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/static-eval/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/static-eval/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "license": "MIT", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/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", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-eval/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==", + "license": "MIT" + }, + "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/string-width-cjs": { + "name": "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/string-width-cjs/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/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "license": "BSD-2-Clause", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "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-ansi-cjs": { + "name": "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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "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==", + "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==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-loader": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", + "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/styled-components": { + "version": "5.3.11", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz", + "integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==", + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^1.1.0", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0", + "react-is": ">= 16.8.0" + } + }, + "node_modules/styled-components/node_modules/@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "node_modules/styled-components/node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, + "node_modules/styled-components/node_modules/babel-plugin-styled-components": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.4.tgz", + "integrity": "sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "lodash": "^4.17.21", + "picomatch": "^2.3.1" + }, + "peerDependencies": { + "styled-components": ">= 2" + } + }, + "node_modules/styled-components/node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/styled-components/node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/styled-components/node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, + "node_modules/styled-components/node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, + "node_modules/stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/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/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "license": "MIT" + }, + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", + "license": "MIT", + "dependencies": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/svgo/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo/node_modules/css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "node_modules/svgo/node_modules/css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/svgo/node_modules/domutils/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "license": "BSD-2-Clause" + }, + "node_modules/svgo/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/svgo/node_modules/nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "~1.0.0" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "license": "MIT" + }, + "node_modules/tailwindcss": { + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "license": "MIT", + "dependencies": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.36.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", + "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "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==", + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-mask-addons": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/text-mask-addons/-/text-mask-addons-3.8.0.tgz", + "integrity": "sha512-VSZSdc/tKn4zGxgpJ+uNBzoW1t472AoAFIlbw1K7hSNXz0DfSBYDJNRxLqgxOfWw1BY2z6DQpm7g0sYZn5qLpg==" + }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "dependencies": { + "utrie": "^1.0.2" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "license": "MIT" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/throat": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", + "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==", + "license": "MIT" + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "license": "MIT" + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "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==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/trello-smooth-dnd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trello-smooth-dnd/-/trello-smooth-dnd-1.0.0.tgz", + "integrity": "sha512-KgYEwmxX08Dl4OmioEv24LSnlNp9jNv8lwTQlUMbMm6B+VuwyQuuuoyu4wlsRweiMCCC6sZXpCCGkmAni/vCaQ==" + }, + "node_modules/tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", + "license": "MIT" + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "license": "Apache-2.0" + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "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==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "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==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "dependencies": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0" + } + }, + "node_modules/uncontrollable/node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "license": "MIT", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==", + "license": "MIT" + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "license": "MIT", + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "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.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/use-debounce": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-7.0.1.tgz", + "integrity": "sha512-fOrzIw2wstbAJuv8PC9Vg4XgwyTLEOdq4y/Z3IhVl8DAE4svRcgyEUvrEXu+BMNgMoc3YND6qLT61kkgEKXh7Q==", + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/use-sound": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/use-sound/-/use-sound-2.2.0.tgz", + "integrity": "sha512-Sa524UuX1piuCHomP/STSjRVhZK6FaXC9qOjfwms2uWp9EErUl+g5ioju/ECfThtexNgcceNunuUtrEr7707Uw==", + "dependencies": { + "howler": "^2.1.3" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "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==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, + "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==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "license": "ISC", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vcard-parser": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vcard-parser/-/vcard-parser-1.0.0.tgz", + "integrity": "sha512-rSEjrjBK3of4VimMR5vBjLLcN5ZCSp9yuVzyx5i4Fwx74Yd0s+DnHtSit/wAAtj1a7/T/qQc0ykwXADoD0+fTQ==" + }, + "node_modules/vest-utils": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/vest-utils/-/vest-utils-0.0.5.tgz", + "integrity": "sha512-uA5NW62n/EdmIOiEHZUQesUSzRnzJgh4R36hZ1omdil0wwYgv7Qobb5omnl1Z03ymopadDtbGXNRxnNFIlwTjQ==" + }, + "node_modules/victory-vendor": { + "version": "36.9.2", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", + "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, + "node_modules/victory-vendor/node_modules/@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==" + }, + "node_modules/victory-vendor/node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==" + }, + "node_modules/victory-vendor/node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/victory-vendor/node_modules/@types/d3-scale": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/victory-vendor/node_modules/@types/d3-shape": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", + "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/victory-vendor/node_modules/@types/d3-time": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", + "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" + }, + "node_modules/victory-vendor/node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==" + }, + "node_modules/victory-vendor/node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", + "license": "MIT", + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "license": "MIT", + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/watchpack": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "license": "MIT", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=10.4" + } + }, + "node_modules/webpack": { + "version": "5.96.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", + "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "license": "MIT", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", + "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", + "license": "MIT", + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.4", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-manifest-plugin": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz", + "integrity": "sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==", + "license": "MIT", + "dependencies": { + "tapable": "^2.0.0", + "webpack-sources": "^2.2.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "peerDependencies": { + "webpack": "^4.44.2 || ^5.47.0" + } + }, + "node_modules/webpack-manifest-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-manifest-plugin/node_modules/webpack-sources": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", + "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", + "license": "MIT", + "dependencies": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webrtc-adapter": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-9.0.1.tgz", + "integrity": "sha512-1AQO+d4ElfVSXyzNVTOewgGT/tAomwwztX/6e3totvyyzXPvXIIuUUjAmyZGbKBKbZOXauuJooZm3g6IuFuiNQ==", + "peer": true, + "dependencies": { + "sdp": "^3.2.0" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">=3.10.0" + } + }, + "node_modules/webrtc-adapter/node_modules/sdp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/sdp/-/sdp-3.2.0.tgz", + "integrity": "sha512-d7wDPgDV3DDiqulJjKiV2865wKsJ34YI+NDREbm+FySq6WuKOikwyNQcm+doLAZ1O6ltdO0SeKle2xMpN3Brgw==", + "peer": true + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "license": "Apache-2.0", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "license": "MIT", + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-encoding/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": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "license": "MIT" + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "license": "MIT" + }, + "node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "license": "MIT", + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "license": "MIT", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "license": "MIT", + "dependencies": { + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", + "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workbox-background-sync": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.6.0.tgz", + "integrity": "sha512-jkf4ZdgOJxC9u2vztxLuPT/UjlH7m/nWRQ/MgGL0v8BJHoZdVGJd18Kck+a0e55wGXdqyHO+4IQTk0685g4MUw==", + "license": "MIT", + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-broadcast-update": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.6.0.tgz", + "integrity": "sha512-nm+v6QmrIFaB/yokJmQ/93qIJ7n72NICxIwQwe5xsZiV2aI93MGGyEyzOzDPVz5THEr5rC3FJSsO3346cId64Q==", + "license": "MIT", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-build": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.6.0.tgz", + "integrity": "sha512-Tjf+gBwOTuGyZwMz2Nk/B13Fuyeo0Q84W++bebbVsfr9iLkDSo6j6PST8tET9HYA58mlRXwlMGpyWO8ETJiXdQ==", + "license": "MIT", + "dependencies": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.1", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.43.1", + "rollup-plugin-terser": "^7.0.0", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "6.6.0", + "workbox-broadcast-update": "6.6.0", + "workbox-cacheable-response": "6.6.0", + "workbox-core": "6.6.0", + "workbox-expiration": "6.6.0", + "workbox-google-analytics": "6.6.0", + "workbox-navigation-preload": "6.6.0", + "workbox-precaching": "6.6.0", + "workbox-range-requests": "6.6.0", + "workbox-recipes": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0", + "workbox-streams": "6.6.0", + "workbox-sw": "6.6.0", + "workbox-window": "6.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/workbox-build/node_modules/@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "license": "MIT", + "dependencies": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "ajv": ">=8" + } + }, + "node_modules/workbox-build/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/workbox-build/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/workbox-build/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/workbox-build/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "license": "BSD-3-Clause", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workbox-build/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "license": "MIT", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/workbox-build/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "license": "BSD-2-Clause" + }, + "node_modules/workbox-build/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "license": "MIT", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/workbox-cacheable-response": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.6.0.tgz", + "integrity": "sha512-JfhJUSQDwsF1Xv3EV1vWzSsCOZn4mQ38bWEBR3LdvOxSPgB65gAM6cS2CX8rkkKHRgiLrN7Wxoyu+TuH67kHrw==", + "deprecated": "workbox-background-sync@6.6.0", + "license": "MIT", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-core": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.6.0.tgz", + "integrity": "sha512-GDtFRF7Yg3DD859PMbPAYPeJyg5gJYXuBQAC+wyrWuuXgpfoOrIQIvFRZnQ7+czTIQjIr1DhLEGFzZanAT/3bQ==", + "license": "MIT" + }, + "node_modules/workbox-expiration": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.6.0.tgz", + "integrity": "sha512-baplYXcDHbe8vAo7GYvyAmlS4f6998Jff513L4XvlzAOxcl8F620O91guoJ5EOf5qeXG4cGdNZHkkVAPouFCpw==", + "license": "MIT", + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-google-analytics": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.6.0.tgz", + "integrity": "sha512-p4DJa6OldXWd6M9zRl0H6vB9lkrmqYFkRQ2xEiNdBFp9U0LhsGO7hsBscVEyH9H2/3eZZt8c97NB2FD9U2NJ+Q==", + "deprecated": "It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained", + "license": "MIT", + "dependencies": { + "workbox-background-sync": "6.6.0", + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "node_modules/workbox-navigation-preload": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.6.0.tgz", + "integrity": "sha512-utNEWG+uOfXdaZmvhshrh7KzhDu/1iMHyQOV6Aqup8Mm78D286ugu5k9MFD9SzBT5TcwgwSORVvInaXWbvKz9Q==", + "license": "MIT", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-precaching": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.6.0.tgz", + "integrity": "sha512-eYu/7MqtRZN1IDttl/UQcSZFkHP7dnvr/X3Vn6Iw6OsPMruQHiVjjomDFCNtd8k2RdjLs0xiz9nq+t3YVBcWPw==", + "license": "MIT", + "dependencies": { + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "node_modules/workbox-range-requests": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.6.0.tgz", + "integrity": "sha512-V3aICz5fLGq5DpSYEU8LxeXvsT//mRWzKrfBOIxzIdQnV/Wj7R+LyJVTczi4CQ4NwKhAaBVaSujI1cEjXW+hTw==", + "license": "MIT", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-recipes": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.6.0.tgz", + "integrity": "sha512-TFi3kTgYw73t5tg73yPVqQC8QQjxJSeqjXRO4ouE/CeypmP2O/xqmB/ZFBBQazLTPxILUQ0b8aeh0IuxVn9a6A==", + "license": "MIT", + "dependencies": { + "workbox-cacheable-response": "6.6.0", + "workbox-core": "6.6.0", + "workbox-expiration": "6.6.0", + "workbox-precaching": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "node_modules/workbox-routing": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.6.0.tgz", + "integrity": "sha512-x8gdN7VDBiLC03izAZRfU+WKUXJnbqt6PG9Uh0XuPRzJPpZGLKce/FkOX95dWHRpOHWLEq8RXzjW0O+POSkKvw==", + "license": "MIT", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-strategies": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.6.0.tgz", + "integrity": "sha512-eC07XGuINAKUWDnZeIPdRdVja4JQtTuc35TZ8SwMb1ztjp7Ddq2CJ4yqLvWzFWGlYI7CG/YGqaETntTxBGdKgQ==", + "license": "MIT", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-streams": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.6.0.tgz", + "integrity": "sha512-rfMJLVvwuED09CnH1RnIep7L9+mj4ufkTyDPVaXPKlhi9+0czCu+SJggWCIFbPpJaAZmp2iyVGLqS3RUmY3fxg==", + "license": "MIT", + "dependencies": { + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0" + } + }, + "node_modules/workbox-sw": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.6.0.tgz", + "integrity": "sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==", + "license": "MIT" + }, + "node_modules/workbox-webpack-plugin": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.6.0.tgz", + "integrity": "sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==", + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "^2.1.0", + "pretty-bytes": "^5.4.1", + "upath": "^1.2.0", + "webpack-sources": "^1.4.3", + "workbox-build": "6.6.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "webpack": "^4.4.0 || ^5.9.0" + } + }, + "node_modules/workbox-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workbox-webpack-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "license": "MIT", + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/workbox-window": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.6.0.tgz", + "integrity": "sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==", + "license": "MIT", + "dependencies": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.6.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==", + "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/wrap-ansi-cjs": { + "name": "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==", + "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/wrap-ansi-cjs/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/wrap-ansi-cjs/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/wrap-ansi-cjs/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/wrap-ansi/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/wrap-ansi/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/wrap-ansi/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/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xlsx": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", + "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", + "dependencies": { + "adler-32": "~1.3.0", + "cfb": "~1.2.1", + "codepage": "~1.15.0", + "crc-32": "~1.2.1", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.3.0" + }, + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "license": "Apache-2.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/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yup": { + "version": "0.32.11", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", + "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", + "dependencies": { + "@babel/runtime": "^7.15.4", + "@types/lodash": "^4.14.175", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + } + }, + "dependencies": { + "@adobe/css-tools": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==" + }, + "@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==" + }, + "@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "requires": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + } + }, + "@babel/compat-data": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==" + }, + "@babel/core": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "requires": { + "ms": "2.1.2" + } + }, + "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==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/eslint-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.9.tgz", + "integrity": "sha512-5UXfgpK0j0Xr/xIdgdLEhOFxaDZ0bRPWJJchRpqOSur/3rZoPbqqki5mm0p4NE2cs28krBEiSM2MB7//afRSQQ==", + "requires": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/generator": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "requires": { + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "requires": { + "@babel/types": "^7.25.9" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz", + "integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==", + "requires": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "requires": { + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", + "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz", + "integrity": "sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "regexpu-core": "^6.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "requires": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + } + }, + "@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "requires": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + } + }, + "@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "requires": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "requires": { + "@babel/types": "^7.25.9" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==" + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", + "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" + } + }, + "@babel/helper-replace-supers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz", + "integrity": "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==", + "requires": { + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.25.9" + } + }, + "@babel/helper-simple-access": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", + "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", + "requires": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", + "requires": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + } + }, + "@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==" + }, + "@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==" + }, + "@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==" + }, + "@babel/helper-wrap-function": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", + "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", + "requires": { + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + } + }, + "@babel/helpers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "requires": { + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" + } + }, + "@babel/parser": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "requires": { + "@babel/types": "^7.26.0" + } + }, + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", + "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + } + }, + "@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", + "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", + "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" + } + }, + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", + "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-proposal-decorators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.25.9.tgz", + "integrity": "sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-decorators": "^7.25.9" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "requires": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", + "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@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==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@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==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@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==", + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@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==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-decorators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz", + "integrity": "sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-syntax-flow": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz", + "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", + "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@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==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@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==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@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==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@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==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@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==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@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==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@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==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@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==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@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==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@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==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", + "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-async-generator-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz", + "integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.25.9" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", + "requires": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz", + "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", + "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-class-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", + "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-class-static-block": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", + "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", + "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", + "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/template": "^7.25.9" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", + "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", + "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", + "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-dynamic-import": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", + "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz", + "integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==", + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-export-namespace-from": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", + "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-flow-strip-types": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.25.9.tgz", + "integrity": "sha512-/VVukELzPDdci7UUsWQaSkhgnjIWXnIyRpM02ldxaVoFK96c41So8JcKT3m0gYjyv7j5FNPGS5vfELrWalkbDA==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-flow": "^7.25.9" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz", + "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", + "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", + "requires": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + } + }, + "@babel/plugin-transform-json-strings": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", + "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", + "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-logical-assignment-operators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", + "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", + "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", + "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", + "requires": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz", + "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==", + "requires": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-simple-access": "^7.25.9" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", + "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", + "requires": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", + "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", + "requires": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", + "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz", + "integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-numeric-separator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", + "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-object-rest-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", + "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", + "requires": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", + "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9" + } + }, + "@babel/plugin-transform-optional-catch-binding": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", + "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", + "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-private-methods": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", + "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-private-property-in-object": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", + "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", + "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-react-constant-elements": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.9.tgz", + "integrity": "sha512-Ncw2JFsJVuvfRsa2lSHiC55kETQVLSnsYGQ1JDDwkUeWGTL/8Tom8aLTnlqgoeuopWrbbGndrc9AlLYrIosrow==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz", + "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", + "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/types": "^7.25.9" + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz", + "integrity": "sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==", + "requires": { + "@babel/plugin-transform-react-jsx": "^7.25.9" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz", + "integrity": "sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", + "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9", + "regenerator-transform": "^0.15.2" + } + }, + "@babel/plugin-transform-regexp-modifiers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", + "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", + "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz", + "integrity": "sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==", + "requires": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", + "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", + "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", + "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz", + "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz", + "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.9.tgz", + "integrity": "sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", + "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-unicode-property-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", + "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", + "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", + "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/preset-env": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz", + "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==", + "requires": { + "@babel/compat-data": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.25.9", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.25.9", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.25.9", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.25.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.25.9", + "@babel/plugin-transform-typeof-symbol": "^7.25.9", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.38.1", + "semver": "^6.3.1" + }, + "dependencies": { + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "requires": {} + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/preset-react": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.25.9.tgz", + "integrity": "sha512-D3to0uSPiWE7rBrdIICCd0tJSIGpLaaGptna2+w7Pft5xMqLpA1sz99DK5TZ1TjGbdQ/VI1eCSZ06dv3lT4JOw==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-transform-react-display-name": "^7.25.9", + "@babel/plugin-transform-react-jsx": "^7.25.9", + "@babel/plugin-transform-react-jsx-development": "^7.25.9", + "@babel/plugin-transform-react-pure-annotations": "^7.25.9" + } + }, + "@babel/preset-typescript": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", + "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", + "requires": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-typescript": "^7.25.9" + } + }, + "@babel/runtime": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", + "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", + "requires": { + "regenerator-runtime": "^0.14.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + } + } + }, + "@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "requires": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + } + }, + "@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "requires": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "@babel/types": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "requires": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" + }, + "@csstools/normalize.css": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.1.1.tgz", + "integrity": "sha512-YAYeJ+Xqh7fUou1d1j9XHl44BmsuThiTr4iNrgCQ3J27IbhXsxXDGZ1cXv8Qvs99d4rBbLiSKy3+WZiet32PcQ==" + }, + "@csstools/postcss-cascade-layers": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", + "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", + "requires": { + "@csstools/selector-specificity": "^2.0.2", + "postcss-selector-parser": "^6.0.10" + } + }, + "@csstools/postcss-color-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", + "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-font-format-keywords": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", + "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-hwb-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", + "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-ic-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", + "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-is-pseudo-class": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", + "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", + "requires": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + } + }, + "@csstools/postcss-nested-calc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz", + "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-normalize-display-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz", + "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-oklab-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", + "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-progressive-custom-properties": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", + "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-stepped-value-functions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", + "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-text-decoration-shorthand": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz", + "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-trigonometric-functions": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz", + "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-unset-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", + "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", + "requires": {} + }, + "@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", + "requires": {} + }, + "@date-io/core": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@date-io/core/-/core-2.17.0.tgz", + "integrity": "sha512-+EQE8xZhRM/hsY0CDTVyayMDDY5ihc4MqXCrPxooKw19yAzUIC6uUqsZeaOFNL9YKTNxYKrJP5DFgE8o5xRCOw==" + }, + "@date-io/date-fns": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@date-io/date-fns/-/date-fns-2.17.0.tgz", + "integrity": "sha512-L0hWZ/mTpy3Gx/xXJ5tq5CzHo0L7ry6KEO9/w/JWiFWFLZgiNVo3ex92gOl3zmzjHqY/3Ev+5sehAr8UnGLEng==", + "requires": { + "@date-io/core": "^2.17.0" + } + }, + "@date-io/moment": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@date-io/moment/-/moment-3.0.0.tgz", + "integrity": "sha512-yIBGP+uBK1Xp0va91uYi0KkJpdXgDWaj5xU1M39YdljQVXea3BM/6eXd7CnlCUwnGhfyanj8AdZvMvpkyjnJUg==", + "requires": { + "@date-io/core": "^3.0.0" + }, + "dependencies": { + "@date-io/core": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@date-io/core/-/core-3.0.0.tgz", + "integrity": "sha512-S3j+IAQVBYNkQzchVVhX40eBkGDreBpScy9RXwTS5j2+k07+62pMVPisQ44Gq76Rqy5AOG/EZXCwBpY/jbemvA==" + } + } + }, + "@emotion/babel-plugin": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", + "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", + "requires": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.2.0", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + }, + "dependencies": { + "@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" + }, + "@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + }, + "convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "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==" + }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + }, + "stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + } + } + }, + "@emotion/is-prop-valid": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz", + "integrity": "sha512-SHetuSLvJDzuNbOdtPVbq6yMMMlLoW5Q94uDqJZqy50gcmAjxFkVqmzqSGEFq9gT2iMuIeKV1PXVWmvUhuZLlQ==", + "requires": { + "@emotion/memoize": "^0.9.0" + }, + "dependencies": { + "@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + } + } + }, + "@emotion/react": { + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.0.tgz", + "integrity": "sha512-WkL+bw1REC2VNV1goQyfxjx1GYJkcc23CRQkXX+vZNLINyfI7o+uUn/rTGPt/xJ3bJHd5GcljgnxHf4wRw5VWQ==", + "peer": true, + "requires": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/cache": "^11.13.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "dependencies": { + "@emotion/cache": { + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "peer": true, + "requires": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "peer": true + }, + "@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "peer": true + }, + "@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "peer": true + }, + "stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "peer": true + } + } + }, + "@emotion/serialize": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.0.tgz", + "integrity": "sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA==", + "requires": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.9.0", + "@emotion/utils": "^1.4.0", + "csstype": "^3.0.2" + }, + "dependencies": { + "@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" + }, + "@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + }, + "@emotion/unitless": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.9.0.tgz", + "integrity": "sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==" + }, + "csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + } + } + }, + "@emotion/styled": { + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz", + "integrity": "sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==", + "requires": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0" + } + }, + "@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", + "requires": {} + }, + "@emotion/utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==" + }, + "@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "requires": { + "eslint-visitor-keys": "^3.4.3" + } + }, + "@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==" + }, + "@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.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" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "requires": { + "type-fest": "^0.20.2" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "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==" + } + } + }, + "@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==" + }, + "@floating-ui/utils": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz", + "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==" + }, + "@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "requires": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" + }, + "@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==" + }, + "@icons/material": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", + "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", + "requires": {} + }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==" + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@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==", + "requires": { + "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" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + } + } + }, + "@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==" + }, + "@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "requires": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + } + } + }, + "@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==", + "requires": { + "jest-get-type": "^29.6.3" + } + }, + "@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "requires": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==" + }, + "expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "requires": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + } + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@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==", + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + } + } + }, + "@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "requires": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + } + }, + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "requires": { + "@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" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "requires": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@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==" + }, + "@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==" + }, + "@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "@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==" + }, + "@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==", + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" + }, + "@material-ui/core": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz", + "integrity": "sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/styles": "^4.11.4", + "@material-ui/system": "^4.12.1", + "@material-ui/types": "5.1.0", + "@material-ui/utils": "^4.11.2", + "@types/react-transition-group": "^4.2.0", + "clsx": "^1.0.4", + "hoist-non-react-statics": "^3.3.2", + "popper.js": "1.16.1-lts", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0", + "react-transition-group": "^4.4.0" + }, + "dependencies": { + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "@material-ui/icons": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.3.tgz", + "integrity": "sha512-IKHlyx6LDh8n19vzwH5RtHIOHl9Tu90aAAxcbWME6kp4dmvODM3UvOHJeMIDzUbd4muuJKHmlNoBN+mDY4XkBA==", + "requires": { + "@babel/runtime": "^7.4.4" + } + }, + "@material-ui/lab": { + "version": "4.0.0-alpha.61", + "resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.61.tgz", + "integrity": "sha512-rSzm+XKiNUjKegj8bzt5+pygZeckNLOr+IjykH8sYdVk7dE9y2ZuUSofiMV2bJk3qU+JHwexmw+q0RyNZB9ugg==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/utils": "^4.11.3", + "clsx": "^1.0.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0" + }, + "dependencies": { + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "@material-ui/pickers": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@material-ui/pickers/-/pickers-3.3.11.tgz", + "integrity": "sha512-pDYjbjUeabapijS2FpSwK/ruJdk7IGeAshpLbKDa3PRRKRy7Nv6sXxAvUg2F+lID/NwUKgBmCYS5bzrl7Xxqzw==", + "requires": { + "@babel/runtime": "^7.6.0", + "@date-io/core": "1.x", + "@types/styled-jsx": "^2.2.8", + "clsx": "^1.0.2", + "react-transition-group": "^4.0.0", + "rifm": "^0.7.0" + }, + "dependencies": { + "@date-io/core": { + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@date-io/core/-/core-1.3.13.tgz", + "integrity": "sha512-AlEKV7TxjeK+jxWVKcCFrfYAk8spX9aCyiToFIiLPtfQbsjmRGLIhb5VZgptQcJdHtLXo7+m0DuurwFgUToQuA==" + }, + "@types/styled-jsx": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@types/styled-jsx/-/styled-jsx-2.2.9.tgz", + "integrity": "sha512-W/iTlIkGEyTBGTEvZCey8EgQlQ5l0DwMqi3iOXlLs2kyBwYTXHKEiU6IZ5EwoRwngL8/dGYuzezSup89ttVHLw==", + "requires": { + "@types/react": "*" + } + }, + "rifm": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rifm/-/rifm-0.7.0.tgz", + "integrity": "sha512-DSOJTWHD67860I5ojetXdEQRIBvF6YcpNe53j0vn1vp9EUb9N80EiZTxgP+FkDKorWC8PZw052kTF4C1GOivCQ==", + "requires": { + "@babel/runtime": "^7.3.1" + } + } + } + }, + "@material-ui/styles": { + "version": "4.11.5", + "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.5.tgz", + "integrity": "sha512-o/41ot5JJiUsIETME9wVLAJrmIWL3j0R0Bj2kCOLbSfqEkKf0fmaPt+5vtblUh5eXr2S+J/8J3DaCb10+CzPGA==", + "requires": { + "@babel/runtime": "^7.4.4", + "@emotion/hash": "^0.8.0", + "@material-ui/types": "5.1.0", + "@material-ui/utils": "^4.11.3", + "clsx": "^1.0.4", + "csstype": "^2.5.2", + "hoist-non-react-statics": "^3.3.2", + "jss": "^10.5.1", + "jss-plugin-camel-case": "^10.5.1", + "jss-plugin-default-unit": "^10.5.1", + "jss-plugin-global": "^10.5.1", + "jss-plugin-nested": "^10.5.1", + "jss-plugin-props-sort": "^10.5.1", + "jss-plugin-rule-value-function": "^10.5.1", + "jss-plugin-vendor-prefixer": "^10.5.1", + "prop-types": "^15.7.2" + }, + "dependencies": { + "@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + }, + "css-vendor": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", + "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", + "requires": { + "@babel/runtime": "^7.8.3", + "is-in-browser": "^1.0.2" + } + }, + "csstype": { + "version": "2.6.21", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", + "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" + }, + "hyphenate-style-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==" + }, + "is-in-browser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", + "integrity": "sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==" + }, + "jss": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss/-/jss-10.10.0.tgz", + "integrity": "sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw==", + "requires": { + "@babel/runtime": "^7.3.1", + "csstype": "^3.0.2", + "is-in-browser": "^1.1.3", + "tiny-warning": "^1.0.2" + }, + "dependencies": { + "csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + } + } + }, + "jss-plugin-camel-case": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.10.0.tgz", + "integrity": "sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw==", + "requires": { + "@babel/runtime": "^7.3.1", + "hyphenate-style-name": "^1.0.3", + "jss": "10.10.0" + } + }, + "jss-plugin-default-unit": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.10.0.tgz", + "integrity": "sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0" + } + }, + "jss-plugin-global": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.10.0.tgz", + "integrity": "sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0" + } + }, + "jss-plugin-nested": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.10.0.tgz", + "integrity": "sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-props-sort": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.10.0.tgz", + "integrity": "sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0" + } + }, + "jss-plugin-rule-value-function": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.10.0.tgz", + "integrity": "sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-vendor-prefixer": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.10.0.tgz", + "integrity": "sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg==", + "requires": { + "@babel/runtime": "^7.3.1", + "css-vendor": "^2.0.8", + "jss": "10.10.0" + } + } + } + }, + "@material-ui/system": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.2.tgz", + "integrity": "sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/utils": "^4.11.3", + "csstype": "^2.5.2", + "prop-types": "^15.7.2" + }, + "dependencies": { + "csstype": { + "version": "2.6.21", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", + "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" + } + } + }, + "@material-ui/types": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz", + "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==", + "requires": {} + }, + "@material-ui/utils": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.3.tgz", + "integrity": "sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg==", + "requires": { + "@babel/runtime": "^7.4.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0" + }, + "dependencies": { + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "@mui/base": { + "version": "5.0.0-beta.40", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz", + "integrity": "sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==", + "requires": { + "@babel/runtime": "^7.23.9", + "@floating-ui/react-dom": "^2.0.8", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.0", + "prop-types": "^15.8.1" + }, + "dependencies": { + "@floating-ui/core": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz", + "integrity": "sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==", + "requires": { + "@floating-ui/utils": "^0.2.7" + } + }, + "@floating-ui/dom": { + "version": "1.6.10", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.10.tgz", + "integrity": "sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==", + "requires": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.7" + } + }, + "@floating-ui/react-dom": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", + "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", + "requires": { + "@floating-ui/dom": "^1.0.0" + } + }, + "@mui/types": { + "version": "7.2.15", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz", + "integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==", + "requires": {} + }, + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + } + } + }, + "@mui/icons-material": { + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.16.7.tgz", + "integrity": "sha512-UrGwDJCXEszbDI7yV047BYU5A28eGJ79keTCP4cc74WyncuVrnurlmIRxaHL8YK+LI1Kzq+/JM52IAkNnv4u+Q==", + "requires": { + "@babel/runtime": "^7.23.9" + } + }, + "@mui/material": { + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.7.tgz", + "integrity": "sha512-cwwVQxBhK60OIOqZOVLFt55t01zmarKJiJUWbk0+8s/Ix5IaUzAShqlJchxsIQ4mSrWqgcKCCXKtIlG5H+/Jmg==", + "requires": { + "@babel/runtime": "^7.23.9", + "@mui/core-downloads-tracker": "^5.16.7", + "@mui/system": "^5.16.7", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.6", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^18.3.1", + "react-transition-group": "^4.4.5" + }, + "dependencies": { + "@mui/core-downloads-tracker": { + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.7.tgz", + "integrity": "sha512-RtsCt4Geed2/v74sbihWzzRs+HsIQCfclHeORh5Ynu2fS4icIKozcSubwuG7vtzq2uW3fOR1zITSP84TNt2GoQ==" + }, + "@mui/types": { + "version": "7.2.15", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz", + "integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==", + "requires": {} + }, + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + }, + "csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + } + } + }, + "@mui/system": { + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.7.tgz", + "integrity": "sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==", + "requires": { + "@babel/runtime": "^7.23.9", + "@mui/private-theming": "^5.16.6", + "@mui/styled-engine": "^5.16.6", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.6", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "dependencies": { + "@emotion/cache": { + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "requires": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + }, + "@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==" + }, + "@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" + }, + "@mui/private-theming": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.6.tgz", + "integrity": "sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==", + "requires": { + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.16.6", + "prop-types": "^15.8.1" + } + }, + "@mui/styled-engine": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.6.tgz", + "integrity": "sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==", + "requires": { + "@babel/runtime": "^7.23.9", + "@emotion/cache": "^11.11.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + } + }, + "@mui/types": { + "version": "7.2.15", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz", + "integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==", + "requires": {} + }, + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + }, + "csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + } + } + }, + "@mui/utils": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz", + "integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==", + "requires": { + "@babel/runtime": "^7.23.9", + "@mui/types": "^7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "dependencies": { + "@mui/types": { + "version": "7.2.15", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz", + "integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==", + "requires": {} + }, + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + } + } + }, + "@mui/x-date-pickers": { + "version": "6.20.2", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.20.2.tgz", + "integrity": "sha512-x1jLg8R+WhvkmUETRfX2wC+xJreMii78EXKLl6r3G+ggcAZlPyt0myID1Amf6hvJb9CtR7CgUo8BwR+1Vx9Ggw==", + "requires": { + "@babel/runtime": "^7.23.2", + "@mui/base": "^5.0.0-beta.22", + "@mui/utils": "^5.14.16", + "@types/react-transition-group": "^4.4.8", + "clsx": "^2.0.0", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "dependencies": { + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + } + } + }, + "@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "requires": { + "eslint-scope": "5.1.1" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true + }, + "@pmmmwh/react-refresh-webpack-plugin": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.15.tgz", + "integrity": "sha512-LFWllMA55pzB9D34w/wXUCf8+c+IYKuJDgxiZ3qMhl64KRMBHYM1I3VdGaD2BV5FNPV2/S2596bppxHbv2ZydQ==", + "requires": { + "ansi-html": "^0.0.9", + "core-js-pure": "^3.23.3", + "error-stack-parser": "^2.0.6", + "html-entities": "^2.1.0", + "loader-utils": "^2.0.4", + "schema-utils": "^4.2.0", + "source-map": "^0.7.3" + } + }, + "@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" + }, + "@restart/hooks": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz", + "integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==", + "requires": { + "dequal": "^2.0.3" + }, + "dependencies": { + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + } + } + }, + "@restart/ui": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.8.0.tgz", + "integrity": "sha512-xJEOXUOTmT4FngTmhdjKFRrVVF0hwCLNPdatLCHkyS4dkiSK12cEu1Y0fjxktjJrdst9jJIc5J6ihMJCoWEN/g==", + "requires": { + "@babel/runtime": "^7.21.0", + "@popperjs/core": "^2.11.6", + "@react-aria/ssr": "^3.5.0", + "@restart/hooks": "^0.4.9", + "@types/warning": "^3.0.0", + "dequal": "^2.0.3", + "dom-helpers": "^5.2.0", + "uncontrollable": "^8.0.1", + "warning": "^4.0.3" + }, + "dependencies": { + "@react-aria/ssr": { + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.5.tgz", + "integrity": "sha512-xEwGKoysu+oXulibNUSkXf8itW0npHHTa6c4AyYeZIJyRoegeteYuFpZUBPtIDE8RfHdNsSmE1ssOkxRnwbkuQ==", + "requires": { + "@swc/helpers": "^0.5.0" + } + }, + "@swc/helpers": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.12.tgz", + "integrity": "sha512-KMZNXiGibsW9kvZAO1Pam2JPTDBm+KSHMMHWdsyI/1DbIZjT2A6Gy3hblVXUMEDvUAKq+e0vL0X0o54owWji7g==", + "requires": { + "tslib": "^2.4.0" + } + }, + "@types/warning": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz", + "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==" + }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + }, + "uncontrollable": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz", + "integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==", + "requires": {} + } + } + }, + "@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + } + }, + "@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "requires": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + }, + "dependencies": { + "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==" + } + } + }, + "@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "requires": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + } + }, + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "dependencies": { + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + } + } + }, + "@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==" + }, + "@rushstack/eslint-patch": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", + "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==" + }, + "@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==" + }, + "@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + }, + "@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "requires": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==" + }, + "@svgr/babel-plugin-remove-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==" + }, + "@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", + "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==" + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", + "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==" + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", + "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==" + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", + "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==" + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", + "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==" + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", + "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==" + }, + "@svgr/babel-preset": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", + "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", + "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", + "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", + "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", + "@svgr/babel-plugin-transform-svg-component": "^5.5.0" + } + }, + "@svgr/core": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", + "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", + "requires": { + "@svgr/plugin-jsx": "^5.5.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.0" + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", + "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", + "requires": { + "@babel/types": "^7.12.6" + } + }, + "@svgr/plugin-jsx": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", + "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", + "requires": { + "@babel/core": "^7.12.3", + "@svgr/babel-preset": "^5.5.0", + "@svgr/hast-util-to-babel-ast": "^5.5.0", + "svg-parser": "^2.0.2" + } + }, + "@svgr/plugin-svgo": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", + "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", + "requires": { + "cosmiconfig": "^7.0.0", + "deepmerge": "^4.2.2", + "svgo": "^1.2.2" + }, + "dependencies": { + "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==" + } + } + }, + "@svgr/webpack": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", + "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", + "requires": { + "@babel/core": "^7.12.3", + "@babel/plugin-transform-react-constant-elements": "^7.12.1", + "@babel/preset-env": "^7.12.1", + "@babel/preset-react": "^7.12.5", + "@svgr/core": "^5.5.0", + "@svgr/plugin-jsx": "^5.5.0", + "@svgr/plugin-svgo": "^5.5.0", + "loader-utils": "^2.0.0" + } + }, + "@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "peer": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "dependencies": { + "@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "peer": true + }, + "lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "peer": true + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "peer": true, + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "peer": true + } + } + }, + "@testing-library/jest-dom": { + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", + "integrity": "sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==", + "requires": { + "@adobe/css-tools": "^4.0.1", + "@babel/runtime": "^7.9.2", + "@types/testing-library__jest-dom": "^5.9.1", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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==", + "requires": { + "color-name": "~1.1.4" + } + }, + "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==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "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==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@testing-library/react": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.7.tgz", + "integrity": "sha512-tzRNp7pzd5QmbtXNG/mhdcl7Awfu/Iz1RaVHY75zTdOkmHCuzMhRL83gWHSgOAcjS3CCbyfwUHMZgRJb4kAfpA==", + "requires": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^7.28.1" + }, + "dependencies": { + "@babel/runtime-corejs3": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.25.0.tgz", + "integrity": "sha512-BOehWE7MgQ8W8Qn0CQnMtg2tHPHPulcS/5AVpFvs2KCK1ET+0WqZqPvnpRpFN81gYoFopdIEJX9Sgjw3ZBccPg==", + "requires": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" + } + }, + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@testing-library/dom": { + "version": "7.31.2", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", + "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^4.2.2", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.6", + "lz-string": "^1.4.4", + "pretty-format": "^26.6.2" + } + }, + "@types/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==" + }, + "@types/yargs": { + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "requires": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + } + }, + "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==", + "requires": { + "color-name": "~1.1.4" + } + }, + "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==" + }, + "lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==" + }, + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "requires": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + } + } + }, + "@testing-library/user-event": { + "version": "12.8.3", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.8.3.tgz", + "integrity": "sha512-IR0iWbFkgd56Bu5ZI/ej8yQwrkCv8Qydx6RzwbKz9faXazR/+5tvYKsZQgyXJiwgpcva127YO6JcWy7YlCfofQ==", + "requires": { + "@babel/runtime": "^7.12.5" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" + }, + "@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" + }, + "@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==", + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@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==", + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "requires": { + "@types/node": "*" + } + }, + "@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "requires": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" + }, + "@types/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" + }, + "@types/eslint": { + "version": "8.56.12", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.12.tgz", + "integrity": "sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==", + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@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==" + }, + "@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + }, + "dependencies": { + "@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + } + } + }, + "@types/express-serve-static-core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz", + "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "@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==", + "requires": { + "@types/node": "*" + } + }, + "@types/hoist-non-react-statics": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", + "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" + }, + "@types/http-proxy": { + "version": "1.17.15", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz", + "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==", + "requires": { + "@types/node": "*" + } + }, + "@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==" + }, + "@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==", + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@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==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "requires": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "@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==" + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" + }, + "@types/lodash": { + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", + "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==" + }, + "@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + }, + "@types/node": { + "version": "22.7.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.9.tgz", + "integrity": "sha512-jrTfRC7FM6nChvU7X2KqcrgquofrWLFDeYC1hKfwNWomVvrn7JIksqf344WN2X/y8xrgqBd2dJATZV4GbatBfg==", + "requires": { + "undici-types": "~6.19.2" + } + }, + "@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==" + }, + "@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" + }, + "@types/q": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.8.tgz", + "integrity": "sha512-hroOstUScF6zhIi+5+x0dzqrHA1EJi+Irri6b1fxolMTqqHIV/Cg77EtnQcZqZCu8hR3mX2BzIxN4/GzI68Kfw==" + }, + "@types/qs": { + "version": "6.9.17", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", + "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==" + }, + "@types/raf": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", + "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", + "optional": true + }, + "@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" + }, + "@types/react": { + "version": "17.0.80", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.80.tgz", + "integrity": "sha512-LrgHIu2lEtIo8M7d1FcI3BdwXWoRQwMoXOZ7+dPTW0lYREjmlHl3P0U1VD0i/9tppOuv8/sam7sOjx34TxSFbA==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "^0.16", + "csstype": "^3.0.2" + }, + "dependencies": { + "csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + } + } + }, + "@types/react-transition-group": { + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz", + "integrity": "sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==", + "requires": { + "@types/react": "*" + } + }, + "@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "requires": { + "@types/node": "*" + } + }, + "@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, + "@types/scheduler": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" + }, + "@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" + }, + "@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "requires": { + "@types/express": "*" + } + }, + "@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "requires": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "requires": { + "@types/node": "*" + } + }, + "@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==" + }, + "@types/testing-library__jest-dom": { + "version": "5.14.9", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz", + "integrity": "sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==", + "requires": { + "@types/jest": "*" + } + }, + "@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==" + }, + "@types/ws": { + "version": "8.5.13", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", + "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", + "requires": { + "@types/node": "*" + } + }, + "@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "@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==" + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "requires": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", + "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "requires": { + "@typescript-eslint/utils": "5.62.0" + } + }, + "@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "requires": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "requires": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==" + }, + "@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "requires": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, + "@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "requires": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==" + }, + "@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "requires": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "requires": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "requires": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "requires": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "requires": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "requires": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" + }, + "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==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "dependencies": { + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + } + } + }, + "acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==" + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + } + } + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "requires": {} + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" + }, + "address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==" + }, + "adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "requires": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + } + }, + "adler-32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==" + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "requires": { + "ajv": "^8.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "requires": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + } + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} + }, + "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==", + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-html": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.9.tgz", + "integrity": "sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg==" + }, + "ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==" + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "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==" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "requires": { + "dequal": "^2.0.3" + }, + "dependencies": { + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + } + } + }, + "array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "requires": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + }, + "array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.reduce": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.7.tgz", + "integrity": "sha512-mzmiUCVwtiD4lgxYP8g7IYy8El8p2CSMePvIbTS7gchKir/L1fgJrk0yDKmAX6mnRQFKNADYIk8nNlTris5H1Q==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-array-method-boxes-properly": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "is-string": "^1.0.7" + } + }, + "array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "requires": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + } + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==" + }, + "async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + }, + "async-mutex": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", + "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", + "requires": { + "tslib": "^2.4.0" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "requires": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + } + }, + "autosize": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/autosize/-/autosize-4.0.4.tgz", + "integrity": "sha512-5yxLQ22O0fCRGoxGfeLSNt3J8LB1v+umtpMnPW6XjkTWXKoN0AmXAIhelJcDtFT/Y/wYWmfE+oqU10Q0b8FhaQ==" + }, + "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==", + "requires": { + "possible-typed-array-names": "^1.0.0" + } + }, + "axe-core": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz", + "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==" + }, + "axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "requires": { + "follow-redirects": "^1.14.0" + } + }, + "axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==" + }, + "babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "requires": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + } + } + }, + "babel-loader": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.4.1.tgz", + "integrity": "sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==", + "requires": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.4", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "dependencies": { + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "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==", + "requires": { + "@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" + } + }, + "babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "requires": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + } + }, + "babel-plugin-named-asset-import": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", + "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", + "requires": {} + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "requires": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + } + }, + "babel-plugin-transform-react-remove-prop-types": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", + "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==" + }, + "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==", + "requires": { + "@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" + } + }, + "babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "requires": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "babel-preset-react-app": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz", + "integrity": "sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==", + "requires": { + "@babel/core": "^7.16.0", + "@babel/plugin-proposal-class-properties": "^7.16.0", + "@babel/plugin-proposal-decorators": "^7.16.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", + "@babel/plugin-proposal-numeric-separator": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.0", + "@babel/plugin-proposal-private-methods": "^7.16.0", + "@babel/plugin-transform-flow-strip-types": "^7.16.0", + "@babel/plugin-transform-react-display-name": "^7.16.0", + "@babel/plugin-transform-runtime": "^7.16.4", + "@babel/preset-env": "^7.16.4", + "@babel/preset-react": "^7.16.0", + "@babel/preset-typescript": "^7.16.0", + "@babel/runtime": "^7.16.3", + "babel-plugin-macros": "^3.1.0", + "babel-plugin-transform-react-remove-prop-types": "^0.4.24" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==" + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" + }, + "bfj": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.1.0.tgz", + "integrity": "sha512-I6MMLkn+anzNdCUp9hMRyui1HaNEUCco50lxbvNS4+EyXg8lN3nJ48PjPWtbH8UVS9CuMoaKE9U2V3l29DaRQw==", + "requires": { + "bluebird": "^3.7.2", + "check-types": "^11.2.3", + "hoopy": "^0.1.4", + "jsonpath": "^1.1.1", + "tryer": "^1.0.1" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==" + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "blueimp-canvas-to-blob": { + "version": "3.29.0", + "resolved": "https://registry.npmjs.org/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.29.0.tgz", + "integrity": "sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg==" + }, + "body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "requires": { + "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.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "raw-body": { + "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==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + } + } + }, + "bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "requires": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "bootstrap": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", + "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", + "requires": {} + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "requires": { + "fill-range": "^7.1.1" + } + }, + "broadcast-channel": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", + "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", + "requires": { + "@babel/runtime": "^7.7.2", + "detect-node": "^2.1.0", + "js-sha3": "0.8.0", + "microseconds": "0.2.0", + "nano-time": "1.0.0", + "oblivious-set": "1.0.0", + "rimraf": "3.0.2", + "unload": "2.2.0" + }, + "dependencies": { + "big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==" + }, + "js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, + "microseconds": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", + "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" + }, + "nano-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", + "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", + "requires": { + "big-integer": "^1.6.16" + } + }, + "oblivious-set": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", + "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" + }, + "unload": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", + "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", + "requires": { + "@babel/runtime": "^7.6.2", + "detect-node": "^2.0.4" + } + } + } + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" + }, + "browserslist": { + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "requires": { + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "requires": { + "node-int64": "^0.4.0" + } + }, + "btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==" + }, + "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==" + }, + "builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==" + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001678", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001678.tgz", + "integrity": "sha512-RR+4U/05gNtps58PEBDZcPWTgEO2MBeoPZ96aQcjmfkBWRIDfN451fW2qyDA9/+HohLLIL5GqiMwA+IB1pWarw==" + }, + "canvg": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", + "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", + "optional": true, + "requires": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + } + }, + "case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==" + }, + "cfb": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", + "requires": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "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==", + "requires": { + "color-name": "~1.1.4" + } + }, + "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==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "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==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "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==" + }, + "chart.js": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", + "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" + }, + "chartjs-plugin-datalabels": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz", + "integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==", + "requires": {} + }, + "check-types": { + "version": "11.2.3", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz", + "integrity": "sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==" + }, + "chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.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" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==" + }, + "ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==" + }, + "cjs-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==" + }, + "classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" + }, + "clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==" + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + } + } + }, + "codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==" + }, + "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==" + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + }, + "common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz", + "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", + "requires": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.0.2", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + } + }, + "compressorjs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/compressorjs/-/compressorjs-1.2.1.tgz", + "integrity": "sha512-+geIjeRnPhQ+LLvvA7wxBQE5ddeLU7pJ3FsKFWirDw6veY3s9iLxAQEw7lXGHnhCJvBujEQWuNnGzZcvCvdkLQ==", + "requires": { + "blueimp-canvas-to-blob": "^3.29.0", + "is-blob": "^2.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==" + }, + "connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==" + }, + "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==", + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + }, + "context": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/context/-/context-4.0.0.tgz", + "integrity": "sha512-B5XTstvpRXt79RkiLR+/XqSCDPrtAsdIZAhZuBCj1bXzuHy7HVbhee+aJ/pHP/+pYrP7YAHdqDH91vfuwqD9/w==", + "requires": { + "vest-utils": "^0.0.5" + } + }, + "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==" + }, + "cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "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==", + "requires": { + "toggle-selection": "^1.0.6" + }, + "dependencies": { + "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==" + } + } + }, + "core-js": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz", + "integrity": "sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==" + }, + "core-js-compat": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", + "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", + "requires": { + "browserslist": "^4.24.2" + } + }, + "core-js-pure": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.39.0.tgz", + "integrity": "sha512-7fEcWwKI4rJinnK+wLTezeg2smbFFdSBP6E2kQZNbnzM2s1rpKQ6aaRteZSSg7FLU3P0HGGVo/gbpfanU36urg==" + }, + "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==" + }, + "cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==" + }, + "cross-spawn": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", + "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, + "css-blank-pseudo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", + "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "requires": {} + }, + "css-has-pseudo": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", + "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "requires": { + "utrie": "^1.0.2" + } + }, + "css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "requires": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + } + }, + "css-minimizer-webpack-plugin": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", + "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", + "requires": { + "cssnano": "^5.0.6", + "jest-worker": "^27.0.2", + "postcss": "^8.3.5", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "css-prefers-color-scheme": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", + "requires": {} + }, + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, + "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==" + }, + "cssdb": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.11.2.tgz", + "integrity": "sha512-lhQ32TFkc1X4eTefGfYPvgovRSzIMofHkigfH8nWtyRL4XJLsRhJFreRvEgKzept7x1rjBuy3J/MurXLaFxW/A==" + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + }, + "cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "requires": { + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + } + }, + "cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "requires": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + } + }, + "cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "requires": {} + }, + "csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "requires": { + "css-tree": "^1.1.2" + }, + "dependencies": { + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + } + } + }, + "damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" + }, + "data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + } + }, + "data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "date-arithmetic": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-arithmetic/-/date-arithmetic-4.1.0.tgz", + "integrity": "sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg==" + }, + "date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "requires": { + "@babel/runtime": "^7.21.0" + } + }, + "dayjs": { + "version": "1.11.12", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz", + "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + }, + "decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==" + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==" + }, + "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==" + }, + "deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==" + }, + "default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "requires": { + "execa": "^5.0.0" + } + }, + "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==", + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, + "define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" + }, + "define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "requires": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "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==" + }, + "detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "requires": { + "address": "^1.0.1", + "debug": "^2.6.0" + } + }, + "didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==" + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "requires": { + "path-type": "^4.0.0" + } + }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "requires": { + "@leichtgewicht/ip-codec": "^2.0.1" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "requires": { + "utila": "~0.4" + } + }, + "dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "requires": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + }, + "dependencies": { + "csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + } + } + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "requires": { + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==" + } + } + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "requires": { + "domelementtype": "^2.2.0" + } + }, + "dompurify": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.7.tgz", + "integrity": "sha512-2q4bEI+coQM8f5ez7kt2xclg1XsecaV9ASJk/54vwlfRRNQfDqJz2pzQ8t0Ix/ToBpXlVjrRIx7pFC/o8itG2Q==", + "optional": true + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" + }, + "dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "requires": { + "jake": "^10.8.5" + } + }, + "electron-to-chromium": { + "version": "1.5.52", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.52.tgz", + "integrity": "sha512-xtoijJTZ+qeucLBDNztDOuQBE1ksqjvNjvqFoST3nGC7fSpqJ+X6BdTBaY5BHG+IhWWmpc6b/KfpeuEDupEPOQ==" + }, + "emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==" + }, + "emoji-mart": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-3.0.1.tgz", + "integrity": "sha512-sxpmMKxqLvcscu6mFn9ITHeZNkGzIvD0BSNFE/LJESPbCA8s1jM6bCDPjWbV31xHq7JXaxgpHxLB54RCbBZSlg==", + "requires": { + "@babel/runtime": "^7.0.0", + "prop-types": "^15.6.0" + } + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "engine.io-client": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz", + "integrity": "sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "requires": { + "ms": "2.1.2" + } + }, + "engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "requires": {} + }, + "xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==" + } + } + }, + "enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + }, + "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==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "requires": { + "stackframe": "^1.3.4" + } + }, + "es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "requires": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + } + }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "requires": { + "get-intrinsic": "^1.2.4" + } + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es-iterator-helpers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz", + "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.3", + "safe-array-concat": "^1.1.2" + } + }, + "es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==" + }, + "es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "requires": { + "es-errors": "^1.3.0" + } + }, + "es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "requires": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + } + }, + "es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "requires": { + "hasown": "^2.0.0" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" + }, + "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==" + }, + "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==" + }, + "escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + } + } + }, + "eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "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==" + }, + "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==", + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "requires": { + "type-fest": "^0.20.2" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + }, + "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==", + "requires": { + "p-locate": "^5.0.0" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "requires": { + "p-limit": "^3.0.2" + } + }, + "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==" + } + } + }, + "eslint-config-react-app": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", + "integrity": "sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==", + "requires": { + "@babel/core": "^7.16.0", + "@babel/eslint-parser": "^7.16.3", + "@rushstack/eslint-patch": "^1.1.0", + "@typescript-eslint/eslint-plugin": "^5.5.0", + "@typescript-eslint/parser": "^5.5.0", + "babel-preset-react-app": "^10.0.1", + "confusing-browser-globals": "^1.0.11", + "eslint-plugin-flowtype": "^8.0.3", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jest": "^25.3.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.27.1", + "eslint-plugin-react-hooks": "^4.3.0", + "eslint-plugin-testing-library": "^5.0.1" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "requires": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "requires": { + "debug": "^3.2.7" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "eslint-plugin-flowtype": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", + "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", + "requires": { + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" + } + }, + "eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "requires": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "^2.0.2" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "eslint-plugin-jest": { + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", + "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", + "requires": { + "@typescript-eslint/experimental-utils": "^5.0.0" + } + }, + "eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "requires": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "dependencies": { + "aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==" + } + } + }, + "eslint-plugin-react": { + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", + "requires": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.1.0", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "^2.0.2" + } + }, + "resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "requires": {} + }, + "eslint-plugin-testing-library": { + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.11.1.tgz", + "integrity": "sha512-5eX9e1Kc2PqVRed3taaLnAAqPZGEX75C+M/rXzUAI3wIg/ZxzUm1OVAwfe/O+vE+6YXOLetSe9g5GKD2ecXipw==", + "requires": { + "@typescript-eslint/utils": "^5.58.0" + } + }, + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "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==" + }, + "eslint-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz", + "integrity": "sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==", + "requires": { + "@types/eslint": "^7.29.0 || ^8.4.1", + "jest-worker": "^28.0.2", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-worker": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", + "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "requires": { + "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" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==" + }, + "expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "requires": { + "@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" + } + }, + "express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "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==" + }, + "fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "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==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "fast-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==" + }, + "fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "requires": { + "reusify": "^1.0.4" + } + }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "requires": { + "bser": "2.1.1" + } + }, + "fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==" + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "requires": { + "flat-cache": "^3.0.4" + } + }, + "file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==" + }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==" + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + } + } + }, + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" + }, + "follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, + "foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" + } + } + }, + "fork-ts-checker-webpack-plugin": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", + "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", + "requires": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "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==" + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + } + } + }, + "form-data": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.2.tgz", + "integrity": "sha512-sJe+TQb2vIaIyO783qN6BlMYWMw3WBOHA1Ay2qxsnjuafEOQFJ2JakedOQirT6D5XPRxDvS7AHYyem9fTpb4LQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "formik": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.6.tgz", + "integrity": "sha512-A+2EI7U7aG296q2TLGvNapDNTZp1khVt5Vk0Q/fyfSROss0V/V6+txt2aJnwEos44IxTCW/LYAi/zgWzlevj+g==", + "requires": { + "@types/hoist-non-react-statics": "^3.3.1", + "deepmerge": "^2.1.1", + "hoist-non-react-statics": "^3.3.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-fast-compare": "^2.0.1", + "tiny-warning": "^1.0.2", + "tslib": "^2.0.0" + } + }, + "formik-material-ui": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/formik-material-ui/-/formik-material-ui-3.0.1.tgz", + "integrity": "sha512-N8oxZIdhY70npRv86IfF6Zaaps9RL3a37XRdq02WDroB3XZC1mXs6lA/zQ09ZYFWYJp/UjI80SKVpVa/xJOJJA==", + "requires": {} + }, + "fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "optional": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "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==" + }, + "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==" + }, + "get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "requires": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "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" + } + }, + "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==", + "requires": { + "is-glob": "^4.0.3" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "requires": { + "global-prefix": "^3.0.0" + } + }, + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "globalize": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/globalize/-/globalize-0.1.1.tgz", + "integrity": "sha512-5e01v8eLGfuQSOvx2MsDMOWS0GFtCx1wPzQSmcHw4hkxFzrQDBO3Xwg/m8Hr/7qXMrHeOIE29qWVzyv06u1TZA==" + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "requires": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "gn-api-sdk-node": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/gn-api-sdk-node/-/gn-api-sdk-node-3.0.4.tgz", + "integrity": "sha512-DZKeTj9bw+Ybe2ZZG9oeWlOEPUm3wsSpLnr/ZAEhxR2Q+b4xZ9juo0tblvc2qi6Q+hnEs03LOR+ULr+kt8mYkQ==", + "requires": { + "axios": "^1.2.1", + "randomstring": "^1.2.2" + }, + "dependencies": { + "axios": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "requires": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "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==" + } + } + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, + "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==" + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + }, + "gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "requires": { + "duplexer": "^0.1.2" + } + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" + }, + "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==" + }, + "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==", + "requires": { + "es-define-property": "^1.0.0" + } + }, + "has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "requires": { + "has-symbols": "^1.0.3" + } + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + }, + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + }, + "dependencies": { + "resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, + "value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + } + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + }, + "dependencies": { + "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==" + } + } + }, + "hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==" + }, + "howler": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/howler/-/howler-2.2.4.tgz", + "integrity": "sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==" + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "requires": { + "whatwg-encoding": "^1.0.5" + } + }, + "html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==" + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + "html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "requires": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + } + }, + "html-webpack-plugin": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz", + "integrity": "sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==", + "requires": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + } + }, + "html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "requires": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + } + }, + "html2pdf.js": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/html2pdf.js/-/html2pdf.js-0.10.2.tgz", + "integrity": "sha512-WyHVeMb18Bp7vYTmBv1GVsThH//K7SRfHdSdhHPkl4JvyQarNQXnailkYn0QUbRRmnN5rdbbmSIGEsPZtzPy2Q==", + "requires": { + "es6-promise": "^4.2.5", + "html2canvas": "^1.0.0", + "jspdf": "^2.3.1" + } + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" + }, + "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==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "dependencies": { + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + } + } + }, + "http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "http-proxy-middleware": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", + "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", + "requires": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "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==" + }, + "i18next": { + "version": "19.9.2", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-19.9.2.tgz", + "integrity": "sha512-0i6cuo6ER6usEOtKajUUDj92zlG+KArFia0857xxiEHAQcUwh/RtOQocui1LPJwunSYT574Pk64aNva1kwtxZg==", + "requires": { + "@babel/runtime": "^7.12.0" + } + }, + "i18next-browser-languagedetector": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.8.tgz", + "integrity": "sha512-Svm+MduCElO0Meqpj1kJAriTC6OhI41VhlT/A0UPjGoPZBhAHIaGE5EfsHlTpgdH09UVX7rcc72pSDDBeKSQQA==", + "requires": { + "@babel/runtime": "^7.19.0" + } + }, + "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==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "requires": {} + }, + "idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" + }, + "identity-obj-proxy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", + "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "requires": { + "harmony-reflect": "^1.4.6" + }, + "dependencies": { + "harmony-reflect": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", + "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==" + } + } + }, + "ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==" + }, + "immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==" + }, + "immutability-helper": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/immutability-helper/-/immutability-helper-2.9.1.tgz", + "integrity": "sha512-r/RmRG8xO06s/k+PIaif2r5rGc3j4Yhc01jSBfwPCXDLYZwp/yxralI37Df1mwmuzcCsen/E/ITKcTEvc1PQmQ==", + "requires": { + "invariant": "^2.2.0" + } + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "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==" + } + } + }, + "import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "requires": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==" + }, + "is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "requires": { + "has-bigints": "^1.0.1" + } + }, + "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==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-blob": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-blob/-/is-blob-2.1.0.tgz", + "integrity": "sha512-SZ/fTft5eUhQM6oF/ZaASFDEdbFVe89Imltn9uZr03wdKMcWNVYSMjQPFtg05QuNkt5l5c135ElvXEQG0rk4tw==" + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "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==" + }, + "is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "requires": { + "hasown": "^2.0.2" + } + }, + "is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "requires": { + "is-typed-array": "^1.1.13" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "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==" + }, + "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==" + }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==" + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" + }, + "is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==" + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==" + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" + }, + "is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" + }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==" + }, + "is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==" + }, + "is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==" + }, + "is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "requires": { + "call-bind": "^1.0.7" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "requires": { + "which-typed-array": "^1.1.14" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==" + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "requires": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + } + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "requires": { + "is-docker": "^2.0.0" + } + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "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==" + }, + "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==", + "requires": { + "@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" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "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==", + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "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==", + "requires": { + "semver": "^7.5.3" + } + }, + "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==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "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==", + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "iterator.prototype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", + "requires": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + } + }, + "jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "requires": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + } + }, + "jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "requires": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + } + } + }, + "jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==" + }, + "expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "requires": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + } + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "requires": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + } + } + }, + "jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "requires": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "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==" + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + } + } + }, + "jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + } + } + }, + "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==" + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + } + } + }, + "jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==" + }, + "expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "requires": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + } + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "requires": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "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==", + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "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==", + "requires": { + "@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" + } + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + } + } + }, + "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==", + "requires": {} + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==" + }, + "jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + } + } + }, + "jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "requires": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + } + } + }, + "jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "requires": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==" + }, + "expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "requires": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + } + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "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==", + "requires": { + "@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" + } + }, + "jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "requires": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-watch-typeahead": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", + "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", + "requires": { + "ansi-escapes": "^4.3.1", + "chalk": "^4.0.0", + "jest-regex-util": "^28.0.0", + "jest-watcher": "^28.0.0", + "slash": "^4.0.0", + "string-length": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "@jest/console": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "requires": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" + }, + "dependencies": { + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + } + } + }, + "@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "requires": { + "@sinclair/typebox": "^0.24.1" + } + }, + "@jest/test-result": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", + "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", + "requires": { + "@jest/console": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "requires": { + "@jest/schemas": "^28.1.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" + } + }, + "@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==" + }, + "emittery": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", + "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==" + }, + "jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + } + } + }, + "jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==" + }, + "jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "requires": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-watcher": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", + "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", + "requires": { + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "jest-util": "^28.1.3", + "string-length": "^4.0.1" + }, + "dependencies": { + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "requires": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==" + }, + "string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "requires": { + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "char-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", + "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==" + } + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==" + } + } + } + } + }, + "jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "requires": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + } + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "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==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + } + }, + "jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==" + }, + "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==" + }, + "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==" + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "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==" + }, + "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==" + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonpath": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz", + "integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==", + "requires": { + "esprima": "1.2.2", + "static-eval": "2.0.2", + "underscore": "1.12.1" + }, + "dependencies": { + "esprima": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", + "integrity": "sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==" + } + } + }, + "jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==" + }, + "jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "jspdf": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.2.tgz", + "integrity": "sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==", + "requires": { + "@babel/runtime": "^7.23.2", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "canvg": "^3.0.6", + "core-js": "^3.6.0", + "dompurify": "^2.5.4", + "fflate": "^0.8.1", + "html2canvas": "^1.0.0-rc.5" + } + }, + "jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "requires": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + }, + "dependencies": { + "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==" + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + } + } + }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "requires": { + "json-buffer": "3.0.1" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + }, + "klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==" + }, + "lamejs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/lamejs/-/lamejs-1.2.1.tgz", + "integrity": "sha512-s7bxvjvYthw6oPLCm5pFxvA84wUROODB8jEO2+CE1adhKgrIvVOlmMgY8zyugxGrvRaDHNJanOiS21/emty6dQ==", + "requires": { + "use-strict": "1.0.1" + }, + "dependencies": { + "use-strict": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/use-strict/-/use-strict-1.0.1.tgz", + "integrity": "sha512-IeiWvvEXfW5ltKVMkxq6FvNf2LojMKvB2OCeja6+ct24S1XOmQw2dGr2JyndwACWAGJva9B7yPHwAmeA9QCqAQ==" + } + } + }, + "language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==" + }, + "language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "requires": { + "language-subtag-registry": "^0.3.20" + } + }, + "launch-editor": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", + "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", + "requires": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "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==" + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==" + }, + "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==" + }, + "loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==" + }, + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + }, + "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==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "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==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "requires": { + "tslib": "^2.0.3" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "luxon": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", + "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==" + }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "requires": { + "tmpl": "1.0.5" + } + }, + "markdown-to-jsx": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.4.7.tgz", + "integrity": "sha512-0+ls1IQZdU6cwM1yu0ZjjiVWYtkbExSyUIFU2ZeDIFuZM1W42Mh4OlJ4nb4apX4H8smxDHRdFaoIVJGwfv5hkg==", + "requires": {} + }, + "match-sorter": { + "version": "6.3.4", + "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.4.tgz", + "integrity": "sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==", + "requires": { + "@babel/runtime": "^7.23.8", + "remove-accents": "0.5.0" + }, + "dependencies": { + "remove-accents": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", + "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==" + } + } + }, + "material-colors": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", + "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" + }, + "material-ui-color": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/material-ui-color/-/material-ui-color-1.2.0.tgz", + "integrity": "sha512-bD2Rww+hakJxD2/19uxc280Vh292DnRStLke2LDFavVtGd5fzOz09zIrHO3ZHlMkJFsvwx6IwiB4/932ftv0sQ==", + "requires": {} + }, + "material-ui-nested-menu-item": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/material-ui-nested-menu-item/-/material-ui-nested-menu-item-1.0.2.tgz", + "integrity": "sha512-LZb8xI0FrAI/A3P2vT3CB9bmSoOFWOK0dikTc1t9VvEpp1a8hZkbVUz7VhETnoLUYu3NXCkgulmXcl3zitqI9A==", + "requires": {} + }, + "material-ui-popup-state": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/material-ui-popup-state/-/material-ui-popup-state-1.9.3.tgz", + "integrity": "sha512-+Ete5Tzw5rXlYfmqptOS8kBUH8vnK5OJsd6IQ7SHtLjU0PsvsmM73M/k8ot0xkX4RmPGuNRsFbK3mlCe/ClQuw==", + "peer": true, + "requires": { + "@babel/runtime": "^7.12.5", + "@material-ui/types": "^6.0.1", + "classnames": "^2.2.6", + "prop-types": "^15.7.2" + }, + "dependencies": { + "@material-ui/types": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-6.0.2.tgz", + "integrity": "sha512-/XUca4wUb9pWimLLdM1PE8KS8rTbDEGohSGkGtk3WST7lm23m+8RYv9uOmrvOg/VSsl4bMiOv4t2/LCb+RLbTg==", + "peer": true, + "requires": {} + } + } + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" + }, + "memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "requires": { + "fs-monkey": "^1.0.4" + } + }, + "memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "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==" + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "mic-recorder-to-mp3": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/mic-recorder-to-mp3/-/mic-recorder-to-mp3-2.2.2.tgz", + "integrity": "sha512-xDkOaHbojW3bdKOGn9CI5dT+Mc0RrfczsX/Y1zGJp3FUB4zei5ZKFnNm7Nguc9v910wkd7T3csnCTq5EtCF3Zw==", + "requires": { + "lamejs": "^1.2.0" + } + }, + "micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "requires": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "mini-css-extract-plugin": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", + "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", + "requires": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "moment-timezone": { + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "requires": { + "moment": "^2.29.4" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "requires": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + } + }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "nanoclone": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", + "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" + }, + "nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" + }, + "negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==" + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + }, + "node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==" + }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" + }, + "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==", + "requires": { + "path-key": "^3.0.0" + } + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "requires": { + "boolbase": "^1.0.0" + } + }, + "nwsapi": { + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==" + }, + "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==" + }, + "object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==" + }, + "object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "requires": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + } + }, + "object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.8.tgz", + "integrity": "sha512-qkHIGe4q0lSYMv0XI4SsBTJz3WaURhLvd0lKSgtVuOsJ2krg4SgMw3PIRQFMp07yi++UR3se2mkcLqsBNpBb/A==", + "requires": { + "array.prototype.reduce": "^1.0.6", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "gopd": "^1.0.1", + "safe-array-concat": "^1.1.2" + } + }, + "object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + } + }, + "object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "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==", + "requires": { + "ee-first": "1.1.1" + }, + "dependencies": { + "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==" + } + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + }, + "optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "requires": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + } + }, + "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==" + }, + "package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "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==", + "requires": { + "callsites": "^3.0.0" + } + }, + "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==", + "requires": { + "@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" + } + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "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==" + }, + "path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "requires": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + } + } + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" + }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==" + }, + "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==", + "requires": { + "find-up": "^4.0.0" + } + }, + "pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + } + } + }, + "popper.js": { + "version": "1.16.1-lts", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz", + "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==" + }, + "possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==" + }, + "postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "requires": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + } + }, + "postcss-attribute-case-insensitive": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", + "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-browser-comments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", + "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", + "requires": {} + }, + "postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "requires": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-functional-notation": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", + "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-hex-alpha": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", + "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-rebeccapurple": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", + "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "requires": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "requires": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-media": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", + "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-properties": { + "version": "12.1.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz", + "integrity": "sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-selectors": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", + "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-dir-pseudo-class": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", + "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "requires": {} + }, + "postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "requires": {} + }, + "postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "requires": {} + }, + "postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "requires": {} + }, + "postcss-double-position-gradients": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", + "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-env-function": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", + "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-flexbugs-fixes": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", + "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", + "requires": {} + }, + "postcss-focus-visible": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", + "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "postcss-focus-within": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", + "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "requires": {} + }, + "postcss-gap-properties": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", + "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", + "requires": {} + }, + "postcss-image-set-function": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", + "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "requires": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "postcss-initial": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "requires": {} + }, + "postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "requires": { + "camelcase-css": "^2.0.1" + } + }, + "postcss-lab-function": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", + "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "requires": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "dependencies": { + "lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==" + }, + "yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==" + } + } + }, + "postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "requires": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + } + }, + "postcss-logical": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", + "requires": {} + }, + "postcss-media-minmax": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "requires": {} + }, + "postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "requires": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + } + }, + "postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "requires": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "requires": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "requires": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "requires": {} + }, + "postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "requires": { + "postcss-selector-parser": "^6.1.1" + } + }, + "postcss-nesting": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", + "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", + "requires": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-normalize": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-10.0.1.tgz", + "integrity": "sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==", + "requires": { + "@csstools/normalize.css": "*", + "postcss-browser-comments": "^4", + "sanitize.css": "*" + } + }, + "postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "requires": {} + }, + "postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "requires": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "requires": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-opacity-percentage": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", + "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", + "requires": {} + }, + "postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "requires": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-overflow-shorthand": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", + "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "requires": {} + }, + "postcss-place": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", + "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-preset-env": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz", + "integrity": "sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==", + "requires": { + "@csstools/postcss-cascade-layers": "^1.1.1", + "@csstools/postcss-color-function": "^1.1.1", + "@csstools/postcss-font-format-keywords": "^1.0.1", + "@csstools/postcss-hwb-function": "^1.0.2", + "@csstools/postcss-ic-unit": "^1.0.1", + "@csstools/postcss-is-pseudo-class": "^2.0.7", + "@csstools/postcss-nested-calc": "^1.0.0", + "@csstools/postcss-normalize-display-values": "^1.0.1", + "@csstools/postcss-oklab-function": "^1.1.1", + "@csstools/postcss-progressive-custom-properties": "^1.3.0", + "@csstools/postcss-stepped-value-functions": "^1.0.1", + "@csstools/postcss-text-decoration-shorthand": "^1.0.0", + "@csstools/postcss-trigonometric-functions": "^1.0.2", + "@csstools/postcss-unset-value": "^1.0.2", + "autoprefixer": "^10.4.13", + "browserslist": "^4.21.4", + "css-blank-pseudo": "^3.0.3", + "css-has-pseudo": "^3.0.4", + "css-prefers-color-scheme": "^6.0.3", + "cssdb": "^7.1.0", + "postcss-attribute-case-insensitive": "^5.0.2", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^4.2.4", + "postcss-color-hex-alpha": "^8.0.4", + "postcss-color-rebeccapurple": "^7.1.1", + "postcss-custom-media": "^8.0.2", + "postcss-custom-properties": "^12.1.10", + "postcss-custom-selectors": "^6.0.3", + "postcss-dir-pseudo-class": "^6.0.5", + "postcss-double-position-gradients": "^3.1.2", + "postcss-env-function": "^4.0.6", + "postcss-focus-visible": "^6.0.4", + "postcss-focus-within": "^5.0.4", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^3.0.5", + "postcss-image-set-function": "^4.0.7", + "postcss-initial": "^4.0.1", + "postcss-lab-function": "^4.2.1", + "postcss-logical": "^5.0.4", + "postcss-media-minmax": "^5.0.0", + "postcss-nesting": "^10.2.0", + "postcss-opacity-percentage": "^1.1.2", + "postcss-overflow-shorthand": "^3.0.4", + "postcss-page-break": "^3.0.4", + "postcss-place": "^7.0.5", + "postcss-pseudo-class-any-link": "^7.1.6", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^6.0.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-pseudo-class-any-link": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", + "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "requires": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "requires": {} + }, + "postcss-selector-not": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", + "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "requires": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + }, + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "requires": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + } + } + } + }, + "postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" + }, + "pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==" + }, + "pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "requires": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "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==", + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "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==" + }, + "promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "requires": { + "asap": "~2.0.6" + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + }, + "dependencies": { + "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==" + } + } + }, + "prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "requires": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "dependencies": { + "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==" + } + } + }, + "property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==" + }, + "proxy-addr": { + "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==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "dependencies": { + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "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==" + } + } + }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" + }, + "qr.js": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", + "integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==" + }, + "qrcode.react": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-1.0.1.tgz", + "integrity": "sha512-8d3Tackk8IRLXTo67Y+c1rpaiXjoz/Dd2HpcMdW//62/x8J1Nbho14Kh8x974t9prsLHN6XqVgcnRiBGFptQmg==", + "requires": { + "loose-envify": "^1.4.0", + "prop-types": "^15.6.0", + "qr.js": "0.0.0" + } + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "requires": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + } + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + }, + "raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "requires": { + "performance-now": "^2.1.0" + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomstring": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/randomstring/-/randomstring-1.3.0.tgz", + "integrity": "sha512-gY7aQ4i1BgwZ8I1Op4YseITAyiDiajeZOPQUbIq9TPGPhUm5FX59izIaOpmKbME1nmnEiABf28d9K2VSii6BBg==", + "requires": { + "randombytes": "2.0.3" + }, + "dependencies": { + "randombytes": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.3.tgz", + "integrity": "sha512-lDVjxQQFoCG1jcrP06LNo2lbWp4QTShEXnhActFBwYuHprllQV6VUpwreApsYqCgD+N1mHoqJ/BI/4eV4R2GYg==" + } + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "react-app-polyfill": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", + "integrity": "sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==", + "requires": { + "core-js": "^3.19.2", + "object-assign": "^4.1.1", + "promise": "^8.1.0", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.9", + "whatwg-fetch": "^3.6.2" + } + }, + "react-big-calendar": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-1.13.2.tgz", + "integrity": "sha512-yzeVRM1I+JloeJXytrZx2lJWKUfLAi5bsgGuBjh3aFSHZrdFcGnfA7LE6pBacdyOG+NGP+332m2MziszkmQWcw==", + "requires": { + "@babel/runtime": "^7.20.7", + "clsx": "^1.2.1", + "date-arithmetic": "^4.1.0", + "dayjs": "^1.11.7", + "dom-helpers": "^5.2.1", + "globalize": "^0.1.1", + "invariant": "^2.2.4", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "luxon": "^3.2.1", + "memoize-one": "^6.0.0", + "moment": "^2.29.4", + "moment-timezone": "^0.5.40", + "prop-types": "^15.8.1", + "react-overlays": "^5.2.1", + "uncontrollable": "^7.2.1" + } + }, + "react-bootstrap": { + "version": "2.10.4", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.4.tgz", + "integrity": "sha512-W3398nBM2CBfmGP2evneEO3ZZwEMPtHs72q++eNw60uDGDAdiGn0f9yNys91eo7/y8CTF5Ke1C0QO8JFVPU40Q==", + "requires": { + "@babel/runtime": "^7.24.7", + "@restart/hooks": "^0.4.9", + "@restart/ui": "^1.6.9", + "@types/react-transition-group": "^4.4.6", + "classnames": "^2.3.2", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.5", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + } + }, + "react-chartjs-2": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-4.3.1.tgz", + "integrity": "sha512-5i3mjP6tU7QSn0jvb8I4hudTzHJqS8l00ORJnVwI2sYu0ihpj83Lv2YzfxunfxTZkscKvZu2F2w9LkwNBhj6xA==", + "requires": {} + }, + "react-color": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz", + "integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==", + "requires": { + "@icons/material": "^0.2.4", + "lodash": "^4.17.15", + "lodash-es": "^4.17.15", + "material-colors": "^1.2.1", + "prop-types": "^15.5.10", + "reactcss": "^1.2.0", + "tinycolor2": "^1.4.1" + } + }, + "react-copy-to-clipboard": { + "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==", + "requires": { + "copy-to-clipboard": "^3.3.1", + "prop-types": "^15.8.1" + } + }, + "react-csv": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/react-csv/-/react-csv-2.2.2.tgz", + "integrity": "sha512-RG5hOcZKZFigIGE8LxIEV/OgS1vigFQT4EkaHeKgyuCbUAu9Nbd/1RYq++bJcJJ9VOqO/n9TZRADsXNDR4VEpw==" + }, + "react-currency-format": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/react-currency-format/-/react-currency-format-1.1.0.tgz", + "integrity": "sha512-WWrEOIp/3GbDSk1wlhFXaBc7IHGT3IwL306DHbGP3GVr4YFa0iS5hHPbKjHa0haruGL4Ly+WG4/5jBHpUtgqZg==", + "requires": { + "prop-types": "^15.6.0" + } + }, + "react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "requires": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "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==" + }, + "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==", + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==" + }, + "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==", + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "requires": { + "p-limit": "^3.0.2" + } + } + } + }, + "react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + }, + "dependencies": { + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } + }, + "react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" + }, + "react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" + }, + "react-feather": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/react-feather/-/react-feather-2.0.10.tgz", + "integrity": "sha512-BLhukwJ+Z92Nmdcs+EMw6dy1Z/VLiJTzEQACDUEnWMClhYnFykJCGWQx+NmwP/qQHGX/5CzQ+TGi8ofg2+HzVQ==", + "requires": { + "prop-types": "^15.7.2" + } + }, + "react-icons": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz", + "integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==", + "requires": {} + }, + "react-input-mask": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-input-mask/-/react-input-mask-2.0.4.tgz", + "integrity": "sha512-1hwzMr/aO9tXfiroiVCx5EtKohKwLk/NT8QlJXHQ4N+yJJFyUuMT+zfTpLBwX/lK3PkuMlievIffncpMZ3HGRQ==", + "requires": { + "invariant": "^2.2.4", + "warning": "^4.0.2" + } + }, + "react-is": { + "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==" + }, + "react-jwt": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/react-jwt/-/react-jwt-1.2.2.tgz", + "integrity": "sha512-1I0Ei1F9m7Nzo1jaeeZk7dpUC4srIVC3bUxDqgD9mFltoTyytp5TFPkK3XMWfLE5iYUsQ+C7tNYbf/gd61D4Sw==", + "requires": { + "fsevents": "^2.3.2" + } + }, + "react-modal-image": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-modal-image/-/react-modal-image-2.6.0.tgz", + "integrity": "sha512-NNc1xPKzFAn0VsNMdJ8NXt6c54aL/z0fcoYmw9qn4SBUONdGl+8LOQ0sTfo0wtdzcjLiby/ncloHcAL+UI+wIA==" + }, + "react-number-format": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-4.9.4.tgz", + "integrity": "sha512-Gq20Z3ugqPLFgeaidnx5on9cNpbQZntPN3QgNAL/WJrNNlQnNznY0LCx7g8xtssmRBw0/hw+SCqw6zAcajooiA==", + "requires": { + "prop-types": "^15.7.2" + } + }, + "react-overlays": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.2.1.tgz", + "integrity": "sha512-GLLSOLWr21CqtJn8geSwQfoJufdt3mfdsnIiQswouuQ2MMPns+ihZklxvsTDKD3cR2tF8ELbi5xUsvqVhR6WvA==", + "requires": { + "@babel/runtime": "^7.13.8", + "@popperjs/core": "^2.11.6", + "@restart/hooks": "^0.4.7", + "@types/warning": "^3.0.0", + "dom-helpers": "^5.2.0", + "prop-types": "^15.7.2", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "dependencies": { + "@types/warning": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz", + "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==" + } + } + }, + "react-popopo": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/react-popopo/-/react-popopo-2.1.9.tgz", + "integrity": "sha512-zXOpcLSpaLZmBxhdtenJzQPLjY81XknVS/tXH4Kv5BBrnYIUPHvVdGmS7+o9s7DjCzzdK7AdVwtG+FVSO0cZ8g==", + "requires": { + "classnames": ">= 2.0", + "prop-types": "^15.7.2", + "react": ">= 16.3", + "react-dom": ">= 16.3", + "styled-components": ">= 4.0" + } + }, + "react-qr-code": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.0.15.tgz", + "integrity": "sha512-MkZcjEXqVKqXEIMVE0mbcGgDpkfSdd8zhuzXEl9QzYeNcw8Hq2oVIzDLWuZN2PQBwM5PWjc2S31K8Q1UbcFMfw==", + "requires": { + "prop-types": "^15.8.1", + "qr.js": "0.0.0" + } + }, + "react-query": { + "version": "3.39.3", + "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", + "integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==", + "requires": { + "@babel/runtime": "^7.5.5", + "broadcast-channel": "^3.4.1", + "match-sorter": "^6.0.2" + } + }, + "react-refresh": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", + "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" + }, + "react-router": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", + "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "requires": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } + } + }, + "react-router-dom": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", + "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", + "requires": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.3.4", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, + "react-scripts": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", + "integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==", + "requires": { + "@babel/core": "^7.16.0", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", + "@svgr/webpack": "^5.5.0", + "babel-jest": "^27.4.2", + "babel-loader": "^8.2.3", + "babel-plugin-named-asset-import": "^0.3.8", + "babel-preset-react-app": "^10.0.1", + "bfj": "^7.0.2", + "browserslist": "^4.18.1", + "camelcase": "^6.2.1", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "css-loader": "^6.5.1", + "css-minimizer-webpack-plugin": "^3.2.0", + "dotenv": "^10.0.0", + "dotenv-expand": "^5.1.0", + "eslint": "^8.3.0", + "eslint-config-react-app": "^7.0.1", + "eslint-webpack-plugin": "^3.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^10.0.0", + "fsevents": "^2.3.2", + "html-webpack-plugin": "^5.5.0", + "identity-obj-proxy": "^3.0.0", + "jest": "^27.4.3", + "jest-resolve": "^27.4.2", + "jest-watch-typeahead": "^1.0.0", + "mini-css-extract-plugin": "^2.4.5", + "postcss": "^8.4.4", + "postcss-flexbugs-fixes": "^5.0.2", + "postcss-loader": "^6.2.1", + "postcss-normalize": "^10.0.1", + "postcss-preset-env": "^7.0.1", + "prompts": "^2.4.2", + "react-app-polyfill": "^3.0.0", + "react-dev-utils": "^12.0.1", + "react-refresh": "^0.11.0", + "resolve": "^1.20.0", + "resolve-url-loader": "^4.0.0", + "sass-loader": "^12.3.0", + "semver": "^7.3.5", + "source-map-loader": "^3.0.0", + "style-loader": "^3.3.1", + "tailwindcss": "^3.0.2", + "terser-webpack-plugin": "^5.2.5", + "webpack": "^5.64.4", + "webpack-dev-server": "^4.6.0", + "webpack-manifest-plugin": "^4.0.2", + "workbox-webpack-plugin": "^6.4.1" + } + }, + "react-smooth": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.1.tgz", + "integrity": "sha512-OE4hm7XqR0jNOq3Qmk9mFLyd6p2+j6bvbPJ7qlB7+oo0eNcL2l7WQzG6MBnT3EXY6xzkLMUBec3AfewJdA0J8w==", + "requires": { + "fast-equals": "^5.0.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "dependencies": { + "fast-equals": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", + "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==" + } + } + }, + "react-text-mask": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-text-mask/-/react-text-mask-5.5.0.tgz", + "integrity": "sha512-SLJlJQxa0uonMXsnXRpv5abIepGmHz77ylQcra0GNd7Jtk4Wj2Mtp85uGQHv1avba2uI8ZvRpIEQPpJKsqRGYw==", + "requires": { + "prop-types": "^15.5.6" + } + }, + "react-to-print": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/react-to-print/-/react-to-print-3.0.2.tgz", + "integrity": "sha512-FS/Z4LLq0bgWaxd7obygFQ8yRFdKW74iE8fIVjFFsPJWIXmuL8CIO+4me1Hj44lrlxQ00gscSNb3BRM8olbwXg==", + "requires": {} + }, + "react-toastify": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.0.0.tgz", + "integrity": "sha512-gmxAFTKV0VVN7s5UEcZdC+bBR1EQtsqXgHJWQgB0G5J8m3Mdxz1Pacm7BJ1nTHkMMNfupruKCu7wUwAq46Z1jg==", + "requires": { + "clsx": "^1.1.1" + } + }, + "react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "requires": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + } + }, + "react-trello": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/react-trello/-/react-trello-2.2.11.tgz", + "integrity": "sha512-Zm7qrPAcFTysUXK6wpa1KhTt7fTadIZgNGYj+blDWGnppFYW7GMi1p+S6J8P9quhzKnIJTSZXVzHA1f4sREIVQ==", + "requires": { + "autosize": "^4.0.2", + "classnames": "^2.2.6", + "immutability-helper": "^2.8.1", + "lodash": "^4.17.11", + "prop-types": "^15.7.2", + "react-popopo": "^2.1.9", + "react-redux": "^5.0.7", + "redux": "^4.0.0", + "redux-actions": "^2.6.1", + "redux-logger": "^3.0.6", + "trello-smooth-dnd": "1.0.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "react-redux": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.1.2.tgz", + "integrity": "sha512-Ns1G0XXc8hDyH/OcBHOxNgQx9ayH3SPxBnFCOidGKSle8pKihysQw2rG/PmciUQRoclhVBO8HMhiRmGXnDja9Q==", + "requires": { + "@babel/runtime": "^7.1.2", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4", + "loose-envify": "^1.1.0", + "prop-types": "^15.6.1", + "react-is": "^16.6.0", + "react-lifecycles-compat": "^3.0.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } + } + }, + "reactcss": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", + "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==", + "requires": { + "lodash": "^4.0.1" + } + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "requires": { + "pify": "^2.3.0" + } + }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "recharts": { + "version": "2.12.7", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.12.7.tgz", + "integrity": "sha512-hlLJMhPQfv4/3NBSAyq3gzGg4h2v69RJh6KU7b3pXYNNAELs9kEoXOjbkxdXpALqKBoVmVptGfLpxdaVYqjmXQ==", + "requires": { + "clsx": "^2.0.0", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.21", + "react-is": "^16.10.2", + "react-smooth": "^4.0.0", + "recharts-scale": "^0.4.4", + "tiny-invariant": "^1.3.1", + "victory-vendor": "^36.6.8" + }, + "dependencies": { + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + }, + "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==" + } + } + }, + "recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "requires": { + "decimal.js-light": "^2.4.1" + }, + "dependencies": { + "decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" + } + } + }, + "recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "requires": { + "minimatch": "^3.0.5" + } + }, + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "dependencies": { + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" + }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "requires": { + "min-indent": "^1.0.0" + } + } + } + }, + "redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "requires": { + "@babel/runtime": "^7.9.2" + } + }, + "redux-actions": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/redux-actions/-/redux-actions-2.6.5.tgz", + "integrity": "sha512-pFhEcWFTYNk7DhQgxMGnbsB1H2glqhQJRQrtPb96kD3hWiZRzXHwwmFPswg6V2MjraXRXWNmuP9P84tvdLAJmw==", + "requires": { + "invariant": "^2.2.4", + "just-curry-it": "^3.1.0", + "loose-envify": "^1.4.0", + "reduce-reducers": "^0.4.3", + "to-camel-case": "^1.0.0" + }, + "dependencies": { + "just-curry-it": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/just-curry-it/-/just-curry-it-3.2.1.tgz", + "integrity": "sha512-Q8206k8pTY7krW32cdmPsP+DqqLgWx/hYPSj9/+7SYqSqz7UuwPbfSe07lQtvuuaVyiSJveXk0E5RydOuWwsEg==" + }, + "reduce-reducers": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/reduce-reducers/-/reduce-reducers-0.4.3.tgz", + "integrity": "sha512-+CNMnI8QhgVMtAt54uQs3kUxC3Sybpa7Y63HR14uGLgI9/QR5ggHvpxwhGGe3wmx5V91YwqQIblN9k5lspAmGw==" + }, + "to-camel-case": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-camel-case/-/to-camel-case-1.0.0.tgz", + "integrity": "sha512-nD8pQi5H34kyu1QDMFjzEIYqk0xa9Alt6ZfrdEMuHCFOfTLhDG5pgTu/aAM9Wt9lXILwlXmWP43b8sav0GNE8Q==", + "requires": { + "to-space-case": "^1.0.0" + } + }, + "to-no-case": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz", + "integrity": "sha512-Z3g735FxuZY8rodxV4gH7LxClE4H0hTIyHNIHdk+vpQxjLm0cwnKXq/OFVZ76SOQmto7txVcwSCwkU5kqp+FKg==" + }, + "to-space-case": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz", + "integrity": "sha512-rLdvwXZ39VOn1IxGL3V6ZstoTbwLRckQmn/U8ZDLuWwIXNpuZDhQ3AiRUlhTbOXFVE9C+dR51wM0CBDhk31VcA==", + "requires": { + "to-no-case": "^1.0.0" + } + } + } + }, + "redux-logger": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-3.0.6.tgz", + "integrity": "sha512-JoCIok7bg/XpqA1JqCqXFypuqBbQzGQySrhFzewB7ThcnysTO30l4VCst86AuB9T9tuT03MAA56Jw2PNhRSNCg==", + "requires": { + "deep-diff": "^0.3.5" + }, + "dependencies": { + "deep-diff": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz", + "integrity": "sha512-yVn6RZmHiGnxRKR9sJb3iVV2XTF1Ghh2DiWRZ3dMnGc43yUdWWF/kX6lQyk3+P84iprfWKU/8zFTrlkvtFm1ug==" + } + } + }, + "reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "requires": { + "regenerate": "^1.4.2" + } + }, + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz", + "integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==" + }, + "regexp.prototype.flags": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.2" + } + }, + "regexpu-core": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", + "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", + "requires": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.11.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + } + }, + "regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==" + }, + "regjsparser": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.2.tgz", + "integrity": "sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA==", + "requires": { + "jsesc": "~3.0.2" + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==" + }, + "renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "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==", + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + }, + "resolve-url-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", + "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", + "requires": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^7.0.35", + "source-map": "0.6.1" + }, + "dependencies": { + "convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "resolve.exports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", + "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==" + }, + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, + "rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "optional": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "rollup": { + "version": "2.79.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", + "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", + "requires": { + "fsevents": "~2.3.2" + } + }, + "rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "requires": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "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==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "requires": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sanitize.css": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", + "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==" + }, + "sass-loader": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", + "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", + "requires": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "requires": { + "xmlchars": "^2.2.0" + } + }, + "schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "dependencies": { + "ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "requires": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + } + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" + }, + "selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "requires": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + } + }, + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "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==", + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + } + }, + "set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==" + }, + "side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + } + }, + "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==" + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "socket.io-client": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz", + "integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.5.2", + "socket.io-parser": "~4.2.4" + }, + "dependencies": { + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" + }, + "source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" + }, + "source-map-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", + "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", + "requires": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.1" + } + }, + "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==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "ssf": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", + "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", + "requires": { + "frac": "~1.1.2" + }, + "dependencies": { + "frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==" + } + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + }, + "stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "stackblur-canvas": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", + "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "optional": true + }, + "stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" + }, + "static-eval": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", + "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", + "requires": { + "escodegen": "^1.8.1" + }, + "dependencies": { + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "requires": { + "prelude-ls": "~1.1.2" + } + } + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==" + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==" + }, + "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==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "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==" + } + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "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==" + } + } + }, + "string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + } + }, + "string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + } + }, + "string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + } + }, + "string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + } + }, + "string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "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==" + }, + "strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==" + }, + "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==" + }, + "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==" + }, + "style-loader": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", + "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "requires": {} + }, + "styled-components": { + "version": "5.3.11", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz", + "integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^1.1.0", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + }, + "dependencies": { + "@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, + "babel-plugin-styled-components": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.4.tgz", + "integrity": "sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "lodash": "^4.17.21", + "picomatch": "^2.3.1" + } + }, + "camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==" + }, + "css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==" + }, + "css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "requires": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + } + } + }, + "stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "requires": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + } + }, + "sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" + }, + "glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + } + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "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==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "optional": true + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==" + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + }, + "dependencies": { + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + } + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } + } + } + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, + "tailwindcss": { + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", + "requires": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + }, + "temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==" + }, + "tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "requires": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "dependencies": { + "type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==" + } + } + }, + "terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "requires": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + } + }, + "terser": { + "version": "5.36.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", + "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", + "requires": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "requires": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "dependencies": { + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "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==", + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "text-mask-addons": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/text-mask-addons/-/text-mask-addons-3.8.0.tgz", + "integrity": "sha512-VSZSdc/tKn4zGxgpJ+uNBzoW1t472AoAFIlbw1K7hSNXz0DfSBYDJNRxLqgxOfWw1BY2z6DQpm7g0sYZn5qLpg==" + }, + "text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "requires": { + "utrie": "^1.0.2" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, + "throat": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", + "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==" + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + }, + "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==", + "requires": { + "is-number": "^7.0.0" + } + }, + "toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" + }, + "tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "dependencies": { + "universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==" + } + } + }, + "tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "requires": { + "punycode": "^2.1.1" + } + }, + "trello-smooth-dnd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trello-smooth-dnd/-/trello-smooth-dnd-1.0.0.tgz", + "integrity": "sha512-KgYEwmxX08Dl4OmioEv24LSnlNp9jNv8lwTQlUMbMm6B+VuwyQuuuoyu4wlsRweiMCCC6sZXpCCGkmAni/vCaQ==" + }, + "tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" + }, + "ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + }, + "tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "requires": { + "minimist": "^1.2.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==" + } + } + }, + "tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "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==" + }, + "type-fest": { + "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==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "dependencies": { + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + } + } + }, + "typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "requires": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "requires": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "requires": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + } + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "peer": true + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "requires": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + }, + "dependencies": { + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + } + } + }, + "underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" + }, + "undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==" + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==" + }, + "unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==" + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==" + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==" + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" + }, + "update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "requires": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, + "url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "use-debounce": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-7.0.1.tgz", + "integrity": "sha512-fOrzIw2wstbAJuv8PC9Vg4XgwyTLEOdq4y/Z3IhVl8DAE4svRcgyEUvrEXu+BMNgMoc3YND6qLT61kkgEKXh7Q==", + "requires": {} + }, + "use-sound": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/use-sound/-/use-sound-2.2.0.tgz", + "integrity": "sha512-Sa524UuX1piuCHomP/STSjRVhZK6FaXC9qOjfwms2uWp9EErUl+g5ioju/ECfThtexNgcceNunuUtrEr7707Uw==", + "requires": { + "howler": "^2.1.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + }, + "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==" + }, + "utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "requires": { + "base64-arraybuffer": "^1.0.2" + } + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + } + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "vcard-parser": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vcard-parser/-/vcard-parser-1.0.0.tgz", + "integrity": "sha512-rSEjrjBK3of4VimMR5vBjLLcN5ZCSp9yuVzyx5i4Fwx74Yd0s+DnHtSit/wAAtj1a7/T/qQc0ykwXADoD0+fTQ==" + }, + "vest-utils": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/vest-utils/-/vest-utils-0.0.5.tgz", + "integrity": "sha512-uA5NW62n/EdmIOiEHZUQesUSzRnzJgh4R36hZ1omdil0wwYgv7Qobb5omnl1Z03ymopadDtbGXNRxnNFIlwTjQ==" + }, + "victory-vendor": { + "version": "36.9.2", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", + "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", + "requires": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + }, + "dependencies": { + "@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==" + }, + "@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==" + }, + "@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "requires": { + "@types/d3-color": "*" + } + }, + "@types/d3-scale": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", + "requires": { + "@types/d3-time": "*" + } + }, + "@types/d3-shape": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", + "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", + "requires": { + "@types/d3-path": "*" + } + }, + "@types/d3-time": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", + "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" + }, + "@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==" + }, + "d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "requires": { + "internmap": "1 - 2" + } + }, + "d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==" + }, + "d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==" + }, + "d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==" + }, + "d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "requires": { + "d3-color": "1 - 3" + } + }, + "d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==" + }, + "d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "requires": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + } + }, + "d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "requires": { + "d3-path": "^3.1.0" + } + }, + "d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "requires": { + "d3-array": "2 - 3" + } + }, + "d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "requires": { + "d3-time": "1 - 3" + } + }, + "d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==" + }, + "internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==" + } + } + }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "requires": { + "xml-name-validator": "^3.0.0" + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "requires": { + "makeerror": "1.0.12" + } + }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "watchpack": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==" + }, + "webpack": { + "version": "5.96.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", + "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", + "requires": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "webpack-dev-middleware": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "requires": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + } + }, + "webpack-dev-server": { + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", + "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", + "requires": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.4", + "ws": "^8.13.0" + }, + "dependencies": { + "ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "requires": {} + } + } + }, + "webpack-manifest-plugin": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz", + "integrity": "sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==", + "requires": { + "tapable": "^2.0.0", + "webpack-sources": "^2.2.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "webpack-sources": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", + "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", + "requires": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + } + } + } + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" + }, + "webrtc-adapter": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-9.0.1.tgz", + "integrity": "sha512-1AQO+d4ElfVSXyzNVTOewgGT/tAomwwztX/6e3totvyyzXPvXIIuUUjAmyZGbKBKbZOXauuJooZm3g6IuFuiNQ==", + "peer": true, + "requires": { + "sdp": "^3.2.0" + }, + "dependencies": { + "sdp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/sdp/-/sdp-3.2.0.tgz", + "integrity": "sha512-d7wDPgDV3DDiqulJjKiV2865wKsJ34YI+NDREbm+FySq6WuKOikwyNQcm+doLAZ1O6ltdO0SeKle2xMpN3Brgw==", + "peer": true + } + } + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "requires": { + "iconv-lite": "0.4.24" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" + }, + "whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-builtin-type": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "requires": { + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" + } + }, + "which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "requires": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + } + }, + "which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "requires": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + } + }, + "wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==" + }, + "word": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", + "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==" + }, + "word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==" + }, + "workbox-background-sync": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.6.0.tgz", + "integrity": "sha512-jkf4ZdgOJxC9u2vztxLuPT/UjlH7m/nWRQ/MgGL0v8BJHoZdVGJd18Kck+a0e55wGXdqyHO+4IQTk0685g4MUw==", + "requires": { + "idb": "^7.0.1", + "workbox-core": "6.6.0" + } + }, + "workbox-broadcast-update": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.6.0.tgz", + "integrity": "sha512-nm+v6QmrIFaB/yokJmQ/93qIJ7n72NICxIwQwe5xsZiV2aI93MGGyEyzOzDPVz5THEr5rC3FJSsO3346cId64Q==", + "requires": { + "workbox-core": "6.6.0" + } + }, + "workbox-build": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.6.0.tgz", + "integrity": "sha512-Tjf+gBwOTuGyZwMz2Nk/B13Fuyeo0Q84W++bebbVsfr9iLkDSo6j6PST8tET9HYA58mlRXwlMGpyWO8ETJiXdQ==", + "requires": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.1", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.43.1", + "rollup-plugin-terser": "^7.0.0", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "6.6.0", + "workbox-broadcast-update": "6.6.0", + "workbox-cacheable-response": "6.6.0", + "workbox-core": "6.6.0", + "workbox-expiration": "6.6.0", + "workbox-google-analytics": "6.6.0", + "workbox-navigation-preload": "6.6.0", + "workbox-precaching": "6.6.0", + "workbox-range-requests": "6.6.0", + "workbox-recipes": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0", + "workbox-streams": "6.6.0", + "workbox-sw": "6.6.0", + "workbox-window": "6.6.0" + }, + "dependencies": { + "@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "requires": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + } + }, + "ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "requires": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "requires": { + "whatwg-url": "^7.0.0" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "requires": { + "punycode": "^2.1.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "workbox-cacheable-response": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.6.0.tgz", + "integrity": "sha512-JfhJUSQDwsF1Xv3EV1vWzSsCOZn4mQ38bWEBR3LdvOxSPgB65gAM6cS2CX8rkkKHRgiLrN7Wxoyu+TuH67kHrw==", + "requires": { + "workbox-core": "6.6.0" + } + }, + "workbox-core": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.6.0.tgz", + "integrity": "sha512-GDtFRF7Yg3DD859PMbPAYPeJyg5gJYXuBQAC+wyrWuuXgpfoOrIQIvFRZnQ7+czTIQjIr1DhLEGFzZanAT/3bQ==" + }, + "workbox-expiration": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.6.0.tgz", + "integrity": "sha512-baplYXcDHbe8vAo7GYvyAmlS4f6998Jff513L4XvlzAOxcl8F620O91guoJ5EOf5qeXG4cGdNZHkkVAPouFCpw==", + "requires": { + "idb": "^7.0.1", + "workbox-core": "6.6.0" + } + }, + "workbox-google-analytics": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.6.0.tgz", + "integrity": "sha512-p4DJa6OldXWd6M9zRl0H6vB9lkrmqYFkRQ2xEiNdBFp9U0LhsGO7hsBscVEyH9H2/3eZZt8c97NB2FD9U2NJ+Q==", + "requires": { + "workbox-background-sync": "6.6.0", + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "workbox-navigation-preload": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.6.0.tgz", + "integrity": "sha512-utNEWG+uOfXdaZmvhshrh7KzhDu/1iMHyQOV6Aqup8Mm78D286ugu5k9MFD9SzBT5TcwgwSORVvInaXWbvKz9Q==", + "requires": { + "workbox-core": "6.6.0" + } + }, + "workbox-precaching": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.6.0.tgz", + "integrity": "sha512-eYu/7MqtRZN1IDttl/UQcSZFkHP7dnvr/X3Vn6Iw6OsPMruQHiVjjomDFCNtd8k2RdjLs0xiz9nq+t3YVBcWPw==", + "requires": { + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "workbox-range-requests": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.6.0.tgz", + "integrity": "sha512-V3aICz5fLGq5DpSYEU8LxeXvsT//mRWzKrfBOIxzIdQnV/Wj7R+LyJVTczi4CQ4NwKhAaBVaSujI1cEjXW+hTw==", + "requires": { + "workbox-core": "6.6.0" + } + }, + "workbox-recipes": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.6.0.tgz", + "integrity": "sha512-TFi3kTgYw73t5tg73yPVqQC8QQjxJSeqjXRO4ouE/CeypmP2O/xqmB/ZFBBQazLTPxILUQ0b8aeh0IuxVn9a6A==", + "requires": { + "workbox-cacheable-response": "6.6.0", + "workbox-core": "6.6.0", + "workbox-expiration": "6.6.0", + "workbox-precaching": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "workbox-routing": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.6.0.tgz", + "integrity": "sha512-x8gdN7VDBiLC03izAZRfU+WKUXJnbqt6PG9Uh0XuPRzJPpZGLKce/FkOX95dWHRpOHWLEq8RXzjW0O+POSkKvw==", + "requires": { + "workbox-core": "6.6.0" + } + }, + "workbox-strategies": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.6.0.tgz", + "integrity": "sha512-eC07XGuINAKUWDnZeIPdRdVja4JQtTuc35TZ8SwMb1ztjp7Ddq2CJ4yqLvWzFWGlYI7CG/YGqaETntTxBGdKgQ==", + "requires": { + "workbox-core": "6.6.0" + } + }, + "workbox-streams": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.6.0.tgz", + "integrity": "sha512-rfMJLVvwuED09CnH1RnIep7L9+mj4ufkTyDPVaXPKlhi9+0czCu+SJggWCIFbPpJaAZmp2iyVGLqS3RUmY3fxg==", + "requires": { + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0" + } + }, + "workbox-sw": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.6.0.tgz", + "integrity": "sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==" + }, + "workbox-webpack-plugin": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.6.0.tgz", + "integrity": "sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==", + "requires": { + "fast-json-stable-stringify": "^2.1.0", + "pretty-bytes": "^5.4.1", + "upath": "^1.2.0", + "webpack-sources": "^1.4.3", + "workbox-build": "6.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "workbox-window": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.6.0.tgz", + "integrity": "sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==", + "requires": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.6.0" + } + }, + "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==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "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==", + "requires": { + "color-name": "~1.1.4" + } + }, + "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==" + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "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==", + "requires": { + "color-name": "~1.1.4" + } + }, + "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==" + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "requires": {} + }, + "xlsx": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", + "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", + "requires": { + "adler-32": "~1.3.0", + "cfb": "~1.2.1", + "codepage": "~1.15.0", + "crc-32": "~1.2.1", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.3.0" + } + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + }, + "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==" + }, + "yup": { + "version": "0.32.11", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", + "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", + "requires": { + "@babel/runtime": "^7.15.4", + "@types/lodash": "^4.14.175", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + } + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..a138503 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,107 @@ +{ + "name": "frontend", + "version": "0.1.0", + "versionSystem": "11.0.0", + "nomeEmpresa": "Waticket SaaS", + "private": true, + "dependencies": { + "@date-io/date-fns": "^2.14.0", + "@date-io/moment": "^3.0.0", + "@emotion/styled": "^11.10.6", + "@floating-ui/utils": "^0.2.4", + "@material-ui/core": "4.12.3", + "@material-ui/icons": "^4.11.3", + "@material-ui/lab": "^4.0.0-alpha.56", + "@material-ui/pickers": "^3.3.10", + "@material-ui/styles": "^4.11.5", + "@mui/icons-material": "^5.14.1", + "@mui/material": "^5.10.13", + "@mui/x-date-pickers": "^6.0.1", + "@testing-library/jest-dom": "^5.11.4", + "@testing-library/react": "^11.0.4", + "@testing-library/user-event": "^12.1.7", + "async-mutex": "^0.5.0", + "axios": "^0.21.1", + "bootstrap": "^5.2.3", + "chart.js": "^3.9.1", + "chartjs-plugin-datalabels": "^2.1.0", + "compressorjs": "^1.2.1", + "context": "^4.0.0", + "date-fns": "^2.16.1", + "emoji-mart": "^3.0.0", + "express": "^4.19.2", + "formik": "^2.2.0", + "formik-material-ui": "^3.0.1", + "gn-api-sdk-node": "^3.0.2", + "html2pdf.js": "^0.10.2", + "i18next": "^19.8.2", + "i18next-browser-languagedetector": "^6.0.1", + "jsonwebtoken": "^9.0.2", + "markdown-to-jsx": "^7.1.0", + "material-ui-color": "^1.2.0", + "material-ui-nested-menu-item": "^1.0.2", + "mic-recorder-to-mp3": "^2.2.2", + "moment": "^2.29.1", + "path-browserify": "^1.0.1", + "qrcode.react": "^1.0.0", + "query-string": "^7.0.0", + "react": "^17.0.2", + "react-big-calendar": "^1.8.7", + "react-bootstrap": "^2.7.0", + "react-chartjs-2": "^4.3.1", + "react-color": "^2.19.3", + "react-copy-to-clipboard": "^5.1.0", + "react-csv": "^2.2.2", + "react-currency-format": "^1.1.0", + "react-dom": "^17.0.2", + "react-feather": "^2.0.10", + "react-icons": "^4.4.0", + "react-input-mask": "^2.0.4", + "react-jwt": "^1.2.1", + "react-modal-image": "^2.5.0", + "react-number-format": "^4.6.4", + "react-qr-code": "^2.0.7", + "react-query": "^3.39.3", + "react-router-dom": "^5.2.0", + "react-scripts": "^5.0.1", + "react-text-mask": "^5.5.0", + "react-to-print": "^3.0.2", + "react-toastify": "9.0.0", + "react-trello": "^2.2.11", + "recharts": "^2.12.7", + "socket.io-client": "^4.7.5", + "styled-components": "^5.3.5", + "text-mask-addons": "^3.8.0", + "use-debounce": "^7.0.0", + "use-sound": "^2.0.1", + "uuid": "^8.3.2", + "vcard-parser": "^1.0.0", + "xlsx": "^0.18.5", + "yup": "^0.32.8" + }, + "scripts": { + "start": "export NODE_OPTIONS=\"--max-old-space-size=8192\" && react-scripts start", + "build": "export NODE_OPTIONS=\"--max-old-space-size=8192\" && NODE_OPTIONS=--openssl-legacy-provider GENERATE_SOURCEMAP=false react-scripts build", + "builddev": "export NODE_OPTIONS=\"--max-old-space-size=8192\" && react-scripts build", + "test": "export NODE_OPTIONS=\"--max-old-space-size=8192\" && react-scripts test", + "eject": "export NODE_OPTIONS=\"--max-old-space-size=8192\" && react-scripts eject" + }, + "eslintConfig": { + "extends": "react-app" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11" + } +} diff --git a/frontend/public/android-chrome-192x192.png b/frontend/public/android-chrome-192x192.png new file mode 100644 index 0000000..59d1ec2 Binary files /dev/null and b/frontend/public/android-chrome-192x192.png differ diff --git a/frontend/public/android-chrome-512x512.png b/frontend/public/android-chrome-512x512.png new file mode 100644 index 0000000..c90d5b1 Binary files /dev/null and b/frontend/public/android-chrome-512x512.png differ diff --git a/frontend/public/apple-touch-icon.png b/frontend/public/apple-touch-icon.png new file mode 100644 index 0000000..916209a Binary files /dev/null and b/frontend/public/apple-touch-icon.png differ diff --git a/frontend/public/facebook.png b/frontend/public/facebook.png new file mode 100644 index 0000000..6944c49 Binary files /dev/null and b/frontend/public/facebook.png differ diff --git a/frontend/public/favicon-16x16.png b/frontend/public/favicon-16x16.png new file mode 100644 index 0000000..8d78fe6 Binary files /dev/null and b/frontend/public/favicon-16x16.png differ diff --git a/frontend/public/favicon-256x256.png b/frontend/public/favicon-256x256.png new file mode 100644 index 0000000..5e77ffe Binary files /dev/null and b/frontend/public/favicon-256x256.png differ diff --git a/frontend/public/favicon-32x32.png b/frontend/public/favicon-32x32.png new file mode 100644 index 0000000..5bac117 Binary files /dev/null and b/frontend/public/favicon-32x32.png differ diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico new file mode 100644 index 0000000..594a202 Binary files /dev/null and b/frontend/public/favicon.ico differ diff --git a/frontend/public/favicon.png b/frontend/public/favicon.png new file mode 100644 index 0000000..c90d5b1 Binary files /dev/null and b/frontend/public/favicon.png differ diff --git a/frontend/public/index.html b/frontend/public/index.html new file mode 100644 index 0000000..d5456db --- /dev/null +++ b/frontend/public/index.html @@ -0,0 +1,112 @@ + + + + Whaticket SaaS + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+
+ + + + + diff --git a/frontend/public/interno.png b/frontend/public/interno.png new file mode 100644 index 0000000..82b59b3 Binary files /dev/null and b/frontend/public/interno.png differ diff --git a/frontend/public/login.png b/frontend/public/login.png new file mode 100644 index 0000000..267718c Binary files /dev/null and b/frontend/public/login.png differ diff --git a/frontend/public/logo_meta.png b/frontend/public/logo_meta.png new file mode 100644 index 0000000..890cc84 Binary files /dev/null and b/frontend/public/logo_meta.png differ diff --git a/frontend/public/logo_typebot.png b/frontend/public/logo_typebot.png new file mode 100644 index 0000000..ae274ed Binary files /dev/null and b/frontend/public/logo_typebot.png differ diff --git a/frontend/public/logo_w.png b/frontend/public/logo_w.png new file mode 100644 index 0000000..68a66d8 Binary files /dev/null and b/frontend/public/logo_w.png differ diff --git a/frontend/public/manifest.json b/frontend/public/manifest.json new file mode 100644 index 0000000..6b51e72 --- /dev/null +++ b/frontend/public/manifest.json @@ -0,0 +1,20 @@ +{ + "short_name": "Whaticket_Saas", + "name": "Whaticket_Saas", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/frontend/public/signup.png b/frontend/public/signup.png new file mode 100644 index 0000000..ff238e5 Binary files /dev/null and b/frontend/public/signup.png differ diff --git a/frontend/public/tela-login.png b/frontend/public/tela-login.png new file mode 100644 index 0000000..03b5e82 Binary files /dev/null and b/frontend/public/tela-login.png differ diff --git a/frontend/public/typebot.png b/frontend/public/typebot.png new file mode 100644 index 0000000..2ae8473 Binary files /dev/null and b/frontend/public/typebot.png differ diff --git a/frontend/server.js b/frontend/server.js new file mode 100644 index 0000000..fa068b0 --- /dev/null +++ b/frontend/server.js @@ -0,0 +1,10 @@ +//simple express server to run frontend production build; +const express = require("express"); +const path = require("path"); +const app = express(); +app.use(express.static(path.join(__dirname, "build"))); +app.get("/*", function (req, res) { + res.sendFile(path.join(__dirname, "build", "index.html")); +}); +app.listen(3500); + diff --git a/frontend/src/App.js b/frontend/src/App.js new file mode 100644 index 0000000..ca17387 --- /dev/null +++ b/frontend/src/App.js @@ -0,0 +1,124 @@ +import React, { useState, useEffect } from "react"; + +import "react-toastify/dist/ReactToastify.css"; +import { QueryClient, QueryClientProvider } from "react-query"; +import lightBackground from '../src/assets/wa-background-light.png'; +import darkBackground from '../src/assets/wa-background-dark.jpg'; +import { ptBR } from "@material-ui/core/locale"; +import { createTheme, ThemeProvider } from "@material-ui/core/styles"; +import { useMediaQuery } from "@material-ui/core"; +import ColorModeContext from "./layout/themeContext"; +import { SocketContext, SocketManager } from './context/Socket/SocketContext'; + +import Routes from "./routes"; + +const queryClient = new QueryClient(); + +const App = () => { + const [locale, setLocale] = useState(); + + const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)"); + const preferredTheme = window.localStorage.getItem("preferredTheme"); + const [mode, setMode] = useState(preferredTheme ? preferredTheme : prefersDarkMode ? "dark" : "light"); + + const colorMode = React.useMemo( + () => ({ + toggleColorMode: () => { + setMode((prevMode) => (prevMode === "light" ? "dark" : "light")); + }, + }), + [] + ); + + const theme = createTheme( + { + scrollbarStyles: { + "&::-webkit-scrollbar": { + width: '8px', + height: '8px', + borderRadius: "8px", + }, + "&::-webkit-scrollbar-thumb": { + boxShadow: 'inset 0 0 6px rgba(0, 0, 0, 0.3)', + backgroundColor: "#52da4d", + borderRadius: "8px", + }, + }, + scrollbarStylesSoft: { + "&::-webkit-scrollbar": { + width: "8px", + borderRadius: "8px", + }, + "&::-webkit-scrollbar-thumb": { + backgroundColor: mode === "light" ? "#F3F3F3" : "#333333", + borderRadius: "8px", + }, + }, + palette: { + type: mode, + primary: { main: mode === "light" ? "#031c9f" : "#FFFFFF" }, + sair: { main: mode === "light" ? "#031c9f" : "#333" }, + vcard: { main: mode === "light" ? "#031c9f" : "#666" }, + textPrimary: mode === "light" ? "#031c9f" : "#FFFFFF", + borderPrimary: mode === "light" ? "#031c9f" : "#FFFFFF", + dark: { main: mode === "light" ? "#333333" : "#F3F3F3" }, + light: { main: mode === "light" ? "#F3F3F3" : "#333333" }, + tabHeaderBackground: mode === "light" ? "#EEE" : "#666", + optionsBackground: mode === "light" ? "#fafafa" : "#333", + options: mode === "light" ? "#fafafa" : "#666", + fontecor: mode === "light" ? "#128c7e" : "#fff", + fancyBackground: mode === "light" ? "#fafafa" : "#333", + bordabox: mode === "light" ? "#eee" : "#333", + newmessagebox: mode === "light" ? "#eee" : "#333", + inputdigita: mode === "light" ? "#fff" : "#666", + contactdrawer: mode === "light" ? "#fff" : "#666", + announcements: mode === "light" ? "#ededed" : "#333", + login: mode === "light" ? "#fff" : "#1C1C1C", + announcementspopover: mode === "light" ? "#fff" : "#666", + chatlist: mode === "light" ? "#eee" : "#666", + boxlist: mode === "light" ? "#ededed" : "#666", + boxchatlist: mode === "light" ? "#ededed" : "#333", + total: mode === "light" ? "#fff" : "#222", + messageIcons: mode === "light" ? "grey" : "#F3F3F3", + inputBackground: mode === "light" ? "#FFFFFF" : "#333", + barraSuperior: mode === "light" ? "linear-gradient(to right, #000359, #000359 , #000359)" : "#666", + boxticket: mode === "light" ? "#EEE" : "#666", + campaigntab: mode === "light" ? "#ededed" : "#666", + mediainput: mode === "light" ? "#ededed" : "#1c1c1c", + contadordash: mode == "light" ? "#fff" : "#fff", + }, + mode, + }, + locale + ); + + useEffect(() => { + const i18nlocale = localStorage.getItem("i18nextLng"); + const browserLocale = + i18nlocale.substring(0, 2) + i18nlocale.substring(3, 5); + + if (browserLocale === "ptBR") { + setLocale(ptBR); + } + }, []); + + useEffect(() => { + window.localStorage.setItem("preferredTheme", mode); + }, [mode]); + + + + return ( + + + + + + + + + + ); +}; + +export default App; diff --git a/frontend/src/assets/android-chrome-192x192.png b/frontend/src/assets/android-chrome-192x192.png new file mode 100644 index 0000000..59d1ec2 Binary files /dev/null and b/frontend/src/assets/android-chrome-192x192.png differ diff --git a/frontend/src/assets/android-chrome-512x512.png b/frontend/src/assets/android-chrome-512x512.png new file mode 100644 index 0000000..c90d5b1 Binary files /dev/null and b/frontend/src/assets/android-chrome-512x512.png differ diff --git a/frontend/src/assets/apple-touch-icon.png b/frontend/src/assets/apple-touch-icon.png new file mode 100644 index 0000000..916209a Binary files /dev/null and b/frontend/src/assets/apple-touch-icon.png differ diff --git a/frontend/src/assets/backgroundStep.png b/frontend/src/assets/backgroundStep.png new file mode 100644 index 0000000..d2d6928 Binary files /dev/null and b/frontend/src/assets/backgroundStep.png differ diff --git a/frontend/src/assets/bg-login.png b/frontend/src/assets/bg-login.png new file mode 100644 index 0000000..7cf2347 Binary files /dev/null and b/frontend/src/assets/bg-login.png differ diff --git a/frontend/src/assets/bg.png b/frontend/src/assets/bg.png new file mode 100644 index 0000000..41f2404 Binary files /dev/null and b/frontend/src/assets/bg.png differ diff --git a/frontend/src/assets/chat_notify.mp3 b/frontend/src/assets/chat_notify.mp3 new file mode 100644 index 0000000..1e5ab73 Binary files /dev/null and b/frontend/src/assets/chat_notify.mp3 differ diff --git a/frontend/src/assets/dialogflow.png b/frontend/src/assets/dialogflow.png new file mode 100644 index 0000000..2b765c5 Binary files /dev/null and b/frontend/src/assets/dialogflow.png differ diff --git a/frontend/src/assets/facebook.png b/frontend/src/assets/facebook.png new file mode 100644 index 0000000..6944c49 Binary files /dev/null and b/frontend/src/assets/facebook.png differ diff --git a/frontend/src/assets/favicon-16x16.png b/frontend/src/assets/favicon-16x16.png new file mode 100644 index 0000000..8d78fe6 Binary files /dev/null and b/frontend/src/assets/favicon-16x16.png differ diff --git a/frontend/src/assets/favicon-256x256.png b/frontend/src/assets/favicon-256x256.png new file mode 100644 index 0000000..5e77ffe Binary files /dev/null and b/frontend/src/assets/favicon-256x256.png differ diff --git a/frontend/src/assets/favicon-32x32.png b/frontend/src/assets/favicon-32x32.png new file mode 100644 index 0000000..5bac117 Binary files /dev/null and b/frontend/src/assets/favicon-32x32.png differ diff --git a/frontend/src/assets/favicon.png b/frontend/src/assets/favicon.png new file mode 100644 index 0000000..c90d5b1 Binary files /dev/null and b/frontend/src/assets/favicon.png differ diff --git a/frontend/src/assets/icons/agendamentos.png b/frontend/src/assets/icons/agendamentos.png new file mode 100644 index 0000000..59d21f7 Binary files /dev/null and b/frontend/src/assets/icons/agendamentos.png differ diff --git a/frontend/src/assets/icons/agendarenvio.png b/frontend/src/assets/icons/agendarenvio.png new file mode 100644 index 0000000..6e4873a Binary files /dev/null and b/frontend/src/assets/icons/agendarenvio.png differ diff --git a/frontend/src/assets/icons/ajuda.png b/frontend/src/assets/icons/ajuda.png new file mode 100644 index 0000000..6db1e06 Binary files /dev/null and b/frontend/src/assets/icons/ajuda.png differ diff --git a/frontend/src/assets/icons/api.png b/frontend/src/assets/icons/api.png new file mode 100644 index 0000000..bdfe1c6 Binary files /dev/null and b/frontend/src/assets/icons/api.png differ diff --git a/frontend/src/assets/icons/apiicon.png b/frontend/src/assets/icons/apiicon.png new file mode 100644 index 0000000..bdfe1c6 Binary files /dev/null and b/frontend/src/assets/icons/apiicon.png differ diff --git a/frontend/src/assets/icons/arquivos.png b/frontend/src/assets/icons/arquivos.png new file mode 100644 index 0000000..4d450df Binary files /dev/null and b/frontend/src/assets/icons/arquivos.png differ diff --git a/frontend/src/assets/icons/campanhas.png b/frontend/src/assets/icons/campanhas.png new file mode 100644 index 0000000..3ca2f3a Binary files /dev/null and b/frontend/src/assets/icons/campanhas.png differ diff --git a/frontend/src/assets/icons/chatinterno.png b/frontend/src/assets/icons/chatinterno.png new file mode 100644 index 0000000..6205f36 Binary files /dev/null and b/frontend/src/assets/icons/chatinterno.png differ diff --git a/frontend/src/assets/icons/conexao.png b/frontend/src/assets/icons/conexao.png new file mode 100644 index 0000000..f810b29 Binary files /dev/null and b/frontend/src/assets/icons/conexao.png differ diff --git a/frontend/src/assets/icons/config.png b/frontend/src/assets/icons/config.png new file mode 100644 index 0000000..c2ba839 Binary files /dev/null and b/frontend/src/assets/icons/config.png differ diff --git a/frontend/src/assets/icons/configuracao.png b/frontend/src/assets/icons/configuracao.png new file mode 100644 index 0000000..1cf0d4f Binary files /dev/null and b/frontend/src/assets/icons/configuracao.png differ diff --git a/frontend/src/assets/icons/contatos.png b/frontend/src/assets/icons/contatos.png new file mode 100644 index 0000000..63b97ec Binary files /dev/null and b/frontend/src/assets/icons/contatos.png differ diff --git a/frontend/src/assets/icons/dashboard.png b/frontend/src/assets/icons/dashboard.png new file mode 100644 index 0000000..ba9e3ac Binary files /dev/null and b/frontend/src/assets/icons/dashboard.png differ diff --git a/frontend/src/assets/icons/email.png b/frontend/src/assets/icons/email.png new file mode 100644 index 0000000..588558c Binary files /dev/null and b/frontend/src/assets/icons/email.png differ diff --git a/frontend/src/assets/icons/emailsenviados.png b/frontend/src/assets/icons/emailsenviados.png new file mode 100644 index 0000000..4ca71dc Binary files /dev/null and b/frontend/src/assets/icons/emailsenviados.png differ diff --git a/frontend/src/assets/icons/empresas.png b/frontend/src/assets/icons/empresas.png new file mode 100644 index 0000000..53b6858 Binary files /dev/null and b/frontend/src/assets/icons/empresas.png differ diff --git a/frontend/src/assets/icons/enviaremail.png b/frontend/src/assets/icons/enviaremail.png new file mode 100644 index 0000000..8a34942 Binary files /dev/null and b/frontend/src/assets/icons/enviaremail.png differ diff --git a/frontend/src/assets/icons/envioagendado.png b/frontend/src/assets/icons/envioagendado.png new file mode 100644 index 0000000..8b09a46 Binary files /dev/null and b/frontend/src/assets/icons/envioagendado.png differ diff --git a/frontend/src/assets/icons/filas.png b/frontend/src/assets/icons/filas.png new file mode 100644 index 0000000..7499573 Binary files /dev/null and b/frontend/src/assets/icons/filas.png differ diff --git a/frontend/src/assets/icons/financeiro.png b/frontend/src/assets/icons/financeiro.png new file mode 100644 index 0000000..4ebe833 Binary files /dev/null and b/frontend/src/assets/icons/financeiro.png differ diff --git a/frontend/src/assets/icons/informativo.png b/frontend/src/assets/icons/informativo.png new file mode 100644 index 0000000..7ef9e75 Binary files /dev/null and b/frontend/src/assets/icons/informativo.png differ diff --git a/frontend/src/assets/icons/integracoes.png b/frontend/src/assets/icons/integracoes.png new file mode 100644 index 0000000..b748ad6 Binary files /dev/null and b/frontend/src/assets/icons/integracoes.png differ diff --git a/frontend/src/assets/icons/kanbam.png b/frontend/src/assets/icons/kanbam.png new file mode 100644 index 0000000..f47fff6 Binary files /dev/null and b/frontend/src/assets/icons/kanbam.png differ diff --git a/frontend/src/assets/icons/listagem.png b/frontend/src/assets/icons/listagem.png new file mode 100644 index 0000000..2429046 Binary files /dev/null and b/frontend/src/assets/icons/listagem.png differ diff --git a/frontend/src/assets/icons/listasdecontatos.png b/frontend/src/assets/icons/listasdecontatos.png new file mode 100644 index 0000000..63b97ec Binary files /dev/null and b/frontend/src/assets/icons/listasdecontatos.png differ diff --git a/frontend/src/assets/icons/painelkanbam.png b/frontend/src/assets/icons/painelkanbam.png new file mode 100644 index 0000000..a21cb88 Binary files /dev/null and b/frontend/src/assets/icons/painelkanbam.png differ diff --git a/frontend/src/assets/icons/prompt.png b/frontend/src/assets/icons/prompt.png new file mode 100644 index 0000000..c9973a9 Binary files /dev/null and b/frontend/src/assets/icons/prompt.png differ diff --git a/frontend/src/assets/icons/respostarapida.png b/frontend/src/assets/icons/respostarapida.png new file mode 100644 index 0000000..a29b6a8 Binary files /dev/null and b/frontend/src/assets/icons/respostarapida.png differ diff --git a/frontend/src/assets/icons/tags.png b/frontend/src/assets/icons/tags.png new file mode 100644 index 0000000..1d87b8b Binary files /dev/null and b/frontend/src/assets/icons/tags.png differ diff --git a/frontend/src/assets/icons/tagskanbam.png b/frontend/src/assets/icons/tagskanbam.png new file mode 100644 index 0000000..019f2c4 Binary files /dev/null and b/frontend/src/assets/icons/tagskanbam.png differ diff --git a/frontend/src/assets/icons/tarefas.png b/frontend/src/assets/icons/tarefas.png new file mode 100644 index 0000000..9408ef8 Binary files /dev/null and b/frontend/src/assets/icons/tarefas.png differ diff --git a/frontend/src/assets/icons/tickets.png b/frontend/src/assets/icons/tickets.png new file mode 100644 index 0000000..e53a68e Binary files /dev/null and b/frontend/src/assets/icons/tickets.png differ diff --git a/frontend/src/assets/icons/usuarios.png b/frontend/src/assets/icons/usuarios.png new file mode 100644 index 0000000..3d8a311 Binary files /dev/null and b/frontend/src/assets/icons/usuarios.png differ diff --git a/frontend/src/assets/interno.png b/frontend/src/assets/interno.png new file mode 100644 index 0000000..82b59b3 Binary files /dev/null and b/frontend/src/assets/interno.png differ diff --git a/frontend/src/assets/login.png b/frontend/src/assets/login.png new file mode 100644 index 0000000..267718c Binary files /dev/null and b/frontend/src/assets/login.png differ diff --git a/frontend/src/assets/logo_meta.png b/frontend/src/assets/logo_meta.png new file mode 100644 index 0000000..890cc84 Binary files /dev/null and b/frontend/src/assets/logo_meta.png differ diff --git a/frontend/src/assets/logo_typebot.png b/frontend/src/assets/logo_typebot.png new file mode 100644 index 0000000..ae274ed Binary files /dev/null and b/frontend/src/assets/logo_typebot.png differ diff --git a/frontend/src/assets/logo_w.png b/frontend/src/assets/logo_w.png new file mode 100644 index 0000000..68a66d8 Binary files /dev/null and b/frontend/src/assets/logo_w.png differ diff --git a/frontend/src/assets/n8n.png b/frontend/src/assets/n8n.png new file mode 100644 index 0000000..3acc578 Binary files /dev/null and b/frontend/src/assets/n8n.png differ diff --git a/frontend/src/assets/phone.png b/frontend/src/assets/phone.png new file mode 100644 index 0000000..e4a6b07 Binary files /dev/null and b/frontend/src/assets/phone.png differ diff --git a/frontend/src/assets/planilha.xlsx b/frontend/src/assets/planilha.xlsx new file mode 100644 index 0000000..2b6030f Binary files /dev/null and b/frontend/src/assets/planilha.xlsx differ diff --git a/frontend/src/assets/sacmais.png b/frontend/src/assets/sacmais.png new file mode 100644 index 0000000..79c85bc Binary files /dev/null and b/frontend/src/assets/sacmais.png differ diff --git a/frontend/src/assets/signup.png b/frontend/src/assets/signup.png new file mode 100644 index 0000000..ff238e5 Binary files /dev/null and b/frontend/src/assets/signup.png differ diff --git a/frontend/src/assets/sound.mp3 b/frontend/src/assets/sound.mp3 new file mode 100644 index 0000000..bd770d8 Binary files /dev/null and b/frontend/src/assets/sound.mp3 differ diff --git a/frontend/src/assets/sound.ogg b/frontend/src/assets/sound.ogg new file mode 100644 index 0000000..5a7c0ab Binary files /dev/null and b/frontend/src/assets/sound.ogg differ diff --git a/frontend/src/assets/tela-login.png b/frontend/src/assets/tela-login.png new file mode 100644 index 0000000..03b5e82 Binary files /dev/null and b/frontend/src/assets/tela-login.png differ diff --git a/frontend/src/assets/typebot.jpg b/frontend/src/assets/typebot.jpg new file mode 100644 index 0000000..99f8b28 Binary files /dev/null and b/frontend/src/assets/typebot.jpg differ diff --git a/frontend/src/assets/typebot.png b/frontend/src/assets/typebot.png new file mode 100644 index 0000000..2ae8473 Binary files /dev/null and b/frontend/src/assets/typebot.png differ diff --git a/frontend/src/assets/wa-background-dark.jpg b/frontend/src/assets/wa-background-dark.jpg new file mode 100644 index 0000000..37dcee0 Binary files /dev/null and b/frontend/src/assets/wa-background-dark.jpg differ diff --git a/frontend/src/assets/wa-background-dark.png b/frontend/src/assets/wa-background-dark.png new file mode 100644 index 0000000..892c3e0 Binary files /dev/null and b/frontend/src/assets/wa-background-dark.png differ diff --git a/frontend/src/assets/wa-background-light.png b/frontend/src/assets/wa-background-light.png new file mode 100644 index 0000000..301d951 Binary files /dev/null and b/frontend/src/assets/wa-background-light.png differ diff --git a/frontend/src/assets/wa-background.png b/frontend/src/assets/wa-background.png new file mode 100644 index 0000000..b76c17b Binary files /dev/null and b/frontend/src/assets/wa-background.png differ diff --git a/frontend/src/assets/webhook.png b/frontend/src/assets/webhook.png new file mode 100644 index 0000000..ca83b4d Binary files /dev/null and b/frontend/src/assets/webhook.png differ diff --git a/frontend/src/components/AnnouncementModal/index.js b/frontend/src/components/AnnouncementModal/index.js new file mode 100644 index 0000000..bb8db61 --- /dev/null +++ b/frontend/src/components/AnnouncementModal/index.js @@ -0,0 +1,340 @@ +import React, { useState, useEffect, useRef } from "react"; + +import * as Yup from "yup"; +import { Formik, Form, Field } from "formik"; +import { toast } from "react-toastify"; + +import { makeStyles } from "@material-ui/core/styles"; +import { green } from "@material-ui/core/colors"; +import Button from "@material-ui/core/Button"; +import TextField from "@material-ui/core/TextField"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import AttachFileIcon from "@material-ui/icons/AttachFile"; +import DeleteOutlineIcon from "@material-ui/icons/DeleteOutline"; +import IconButton from "@material-ui/core/IconButton"; + +import { i18n } from "../../translate/i18n"; +import { head } from "lodash"; + +import api from "../../services/api"; +import toastError from "../../errors/toastError"; +import { + FormControl, + Grid, + InputLabel, + MenuItem, + Select, +} from "@material-ui/core"; +import ConfirmationModal from "../ConfirmationModal"; + +const useStyles = makeStyles((theme) => ({ + root: { + display: "flex", + flexWrap: "wrap", + }, + multFieldLine: { + display: "flex", + "& > *:not(:last-child)": { + marginRight: theme.spacing(1), + }, + }, + + btnWrapper: { + position: "relative", + }, + + buttonProgress: { + color: green[500], + position: "absolute", + top: "50%", + left: "50%", + marginTop: -12, + marginLeft: -12, + }, + formControl: { + margin: theme.spacing(1), + minWidth: 120, + }, + colorAdorment: { + width: 20, + height: 20, + }, +})); + +const AnnouncementSchema = Yup.object().shape({ + title: Yup.string().required("Obrigatório"), + text: Yup.string().required("Obrigatório"), +}); + +const AnnouncementModal = ({ open, onClose, announcementId, reload }) => { + const classes = useStyles(); + + const initialState = { + title: "", + text: "", + priority: 3, + status: true, + }; + + const [confirmationOpen, setConfirmationOpen] = useState(false); + const [announcement, setAnnouncement] = useState(initialState); + const [attachment, setAttachment] = useState(null); + const attachmentFile = useRef(null); + + useEffect(() => { + try { + (async () => { + if (!announcementId) return; + + const { data } = await api.get(`/announcements/${announcementId}`); + setAnnouncement((prevState) => { + return { ...prevState, ...data }; + }); + })(); + } catch (err) { + toastError(err); + } + }, [announcementId, open]); + + const handleClose = () => { + setAnnouncement(initialState); + setAttachment(null); + onClose(); + }; + + const handleAttachmentFile = (e) => { + const file = head(e.target.files); + if (file) { + setAttachment(file); + } + }; + + const handleSaveAnnouncement = async (values) => { + const announcementData = { ...values }; + try { + if (announcementId) { + await api.put(`/announcements/${announcementId}`, announcementData); + if (attachment != null) { + const formData = new FormData(); + formData.append("typeArch", "announcements"); + formData.append("file", attachment); + await api.post( + `/announcements/${announcementId}/media-upload`, + formData + ); + } + } else { + const { data } = await api.post("/announcements", announcementData); + if (attachment != null) { + const formData = new FormData(); + formData.append("typeArch", "announcements"); + formData.append("file", attachment); + await api.post(`/announcements/${data.id}/media-upload`, formData); + } + } + toast.success(i18n.t("announcements.toasts.success")); + if (typeof reload == "function") { + reload(); + } + } catch (err) { + toastError(err); + } + handleClose(); + }; + + const deleteMedia = async () => { + if (attachment) { + setAttachment(null); + attachmentFile.current.value = null; + } + + if (announcement.mediaPath) { + await api.delete(`/announcements/${announcement.id}/media-upload`); + setAnnouncement((prev) => ({ + ...prev, + mediaPath: null, + })); + toast.success(i18n.t("announcements.toasts.deleted")); + if (typeof reload == "function") { + reload(); + } + } + }; + + return ( +
+ setConfirmationOpen(false)} + onConfirm={deleteMedia} + > + {i18n.t("announcements.confirmationModal.deleteMessage")} + + + + {announcementId + ? `${i18n.t("announcements.dialog.edit")}` + : `${i18n.t("announcements.dialog.add")}`} + +
+ handleAttachmentFile(e)} + /> +
+ { + setTimeout(() => { + handleSaveAnnouncement(values); + actions.setSubmitting(false); + }, 400); + }} + > + {({ touched, errors, isSubmitting, values }) => ( +
+ + + + + + + + + + + + {i18n.t("announcements.dialog.form.status")} + + + Ativo + Inativo + + + + + + + {i18n.t("announcements.dialog.form.priority")} + + + Alta + Média + Baixa + + + + {(announcement.mediaPath || attachment) && ( + + + setConfirmationOpen(true)} + color="secondary" + > + + + + )} + + + + {!attachment && !announcement.mediaPath && ( + + )} + + + +
+ )} +
+
+
+ ); +}; + +export default AnnouncementModal; diff --git a/frontend/src/components/AnnouncementsPopover/index.js b/frontend/src/components/AnnouncementsPopover/index.js new file mode 100644 index 0000000..901b728 --- /dev/null +++ b/frontend/src/components/AnnouncementsPopover/index.js @@ -0,0 +1,336 @@ +import React, { useEffect, useReducer, useState, useContext } from "react"; +import { makeStyles } from "@material-ui/core/styles"; +import toastError from "../../errors/toastError"; +import Popover from "@material-ui/core/Popover"; +import AnnouncementIcon from "@material-ui/icons/Announcement"; +import Notifications from "@material-ui/icons/Notifications" + +import { + Avatar, + Badge, + IconButton, + List, + ListItem, + ListItemAvatar, + ListItemText, + Dialog, + Paper, + Typography, + DialogTitle, + DialogContent, + DialogActions, + Button, + DialogContentText, +} from "@material-ui/core"; +import api from "../../services/api"; +import { isArray } from "lodash"; +import moment from "moment"; +import { SocketContext } from "../../context/Socket/SocketContext"; + +const useStyles = makeStyles((theme) => ({ + mainPaper: { + flex: 1, + maxHeight: 3000, + maxWidth: 5000, + padding: theme.spacing(1), + overflowY: "scroll", + ...theme.scrollbarStyles, + }, +})); + +function AnnouncementDialog({ announcement, open, handleClose }) { + // const getMediaPath = (filename) => { + // return path.join(`${process.env.REACT_APP_BACKEND_URL}`,"public", "announcements",`${filename}`); + // }; + return ( + handleClose()} + aria-labelledby="alert-dialog-title" + aria-describedby="alert-dialog-description" + > + {announcement.title} + + {announcement.mediaPath && ( +
+ {`announcement +
+ )} + + {announcement.text} + +
+ + + +
+ ); +} + +const reducer = (state, action) => { + if (action.type === "LOAD_ANNOUNCEMENTS") { + const announcements = action.payload; + const newAnnouncements = []; + + if (isArray(announcements)) { + announcements.forEach((announcement) => { + const announcementIndex = state.findIndex( + (u) => u.id === announcement.id + ); + if (announcementIndex !== -1) { + state[announcementIndex] = announcement; + } else { + newAnnouncements.push(announcement); + } + }); + } + + return [...state, ...newAnnouncements]; + } + + if (action.type === "UPDATE_ANNOUNCEMENTS") { + const announcement = action.payload; + const announcementIndex = state.findIndex((u) => u.id === announcement.id); + + if (announcementIndex !== -1) { + state[announcementIndex] = announcement; + return [...state]; + } else { + return [announcement, ...state]; + } + } + + if (action.type === "DELETE_ANNOUNCEMENT") { + const announcementId = action.payload; + + const announcementIndex = state.findIndex((u) => u.id === announcementId); + if (announcementIndex !== -1) { + state.splice(announcementIndex, 1); + } + return [...state]; + } + + if (action.type === "RESET") { + return []; + } +}; + +export default function AnnouncementsPopover() { + const classes = useStyles(); + + const [loading, setLoading] = useState(false); + const [anchorEl, setAnchorEl] = useState(null); + const [pageNumber, setPageNumber] = useState(1); + const [hasMore, setHasMore] = useState(false); + const [searchParam] = useState(""); + const [announcements, dispatch] = useReducer(reducer, []); + const [invisible, setInvisible] = useState(false); + const [announcement, setAnnouncement] = useState({}); + const [showAnnouncementDialog, setShowAnnouncementDialog] = useState(false); + + const socketManager = useContext(SocketContext); + + useEffect(() => { + dispatch({ type: "RESET" }); + setPageNumber(1); + }, [searchParam]); + + useEffect(() => { + setLoading(true); + const delayDebounceFn = setTimeout(() => { + fetchAnnouncements(); + }, 500); + return () => clearTimeout(delayDebounceFn); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [searchParam, pageNumber]); + + useEffect(() => { + const companyId = localStorage.getItem("companyId"); + const socket = socketManager.getSocket(companyId); + + if (!socket) { + return () => {}; + } + + socket.on(`company-announcement`, (data) => { + if (data.action === "update" || data.action === "create") { + dispatch({ type: "UPDATE_ANNOUNCEMENTS", payload: data.record }); + setInvisible(false); + } + if (data.action === "delete") { + dispatch({ type: "DELETE_ANNOUNCEMENT", payload: +data.id }); + } + }); + return () => { + socket.disconnect(); + }; + }, [socketManager]); + + const fetchAnnouncements = async () => { + try { + const { data } = await api.get("/announcements/", { + params: { searchParam, pageNumber }, + }); + dispatch({ type: "LOAD_ANNOUNCEMENTS", payload: data.records }); + setHasMore(data.hasMore); + setLoading(false); + } catch (err) { + toastError(err); + } + }; + + const loadMore = () => { + setPageNumber((prevState) => prevState + 1); + }; + + const handleScroll = (e) => { + if (!hasMore || loading) return; + const { scrollTop, scrollHeight, clientHeight } = e.currentTarget; + if (scrollHeight - (scrollTop + 100) < clientHeight) { + loadMore(); + } + }; + + const handleClick = (event) => { + setAnchorEl(event.currentTarget); + setInvisible(true); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + + const borderPriority = (priority) => { + if (priority === 1) { + return "4px solid #b81111"; + } + if (priority === 2) { + return "4px solid orange"; + } + if (priority === 3) { + return "4px solid grey"; + } + }; + + {/* const getMediaPath = (filename) => { + return `${process.env.REACT_APP_BACKEND_URL}/public/${filename}`; + };*/} + + const handleShowAnnouncementDialog = (record) => { + setAnnouncement(record); + setShowAnnouncementDialog(true); + setAnchorEl(null); + }; + + const open = Boolean(anchorEl); + const id = open ? "simple-popover" : undefined; + + return ( +
+ setShowAnnouncementDialog(false)} + /> + + + + + + + + + {isArray(announcements) && + announcements.map((item, key) => ( + handleShowAnnouncementDialog(item)} + > + {item.mediaPath && ( + + + + )} + + + {moment(item.createdAt).format("DD/MM/YYYY")} + + + + {item.text} + + + } + /> + + ))} + {isArray(announcements) && announcements.length === 0 && ( + + )} + + + +
+ ); +} diff --git a/frontend/src/components/AudioModal/index.js b/frontend/src/components/AudioModal/index.js new file mode 100644 index 0000000..0dc3706 --- /dev/null +++ b/frontend/src/components/AudioModal/index.js @@ -0,0 +1,82 @@ +import { Button } from "@material-ui/core"; +import React, { useRef, useEffect, useState } from "react"; + +const LS_NAME = 'audioMessageRate'; + +const AudioModal = ({url}) => { + const audioRef = useRef(null); + const [audioRate, setAudioRate] = useState(parseFloat(localStorage.getItem(LS_NAME) || "1")); + const [showButtonRate, setShowButtonRate] = useState(false); + const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; + + useEffect(() => { + audioRef.current.playbackRate = audioRate; + localStorage.setItem(LS_NAME, audioRate); + }, [audioRate]); + + useEffect(() => { + audioRef.current.onplaying = () => { + setShowButtonRate(true); + }; + audioRef.current.onpause = () => { + setShowButtonRate(false); + }; + audioRef.current.onended = () => { + setShowButtonRate(false); + }; + }, []); + + const toggleRate = () => { + let newRate = null; + + switch (audioRate) { + case 0.5: + newRate = 1; + break; + case 1: + newRate = 1.5; + break; + case 1.5: + newRate = 2; + break; + case 2: + newRate = 0.5; + break; + default: + newRate = 1; + break; + } + + setAudioRate(newRate); + }; + + const getAudioSource = () => { + let sourceUrl = url; + + if (isIOS) { + sourceUrl = sourceUrl.replace(".ogg", ".mp3"); + } + + return ( + + ); + }; + + return ( + <> + + {showButtonRate && ( + + )} + + ); +} + +export default AudioModal; \ No newline at end of file diff --git a/frontend/src/components/BackdropLoading/index.js b/frontend/src/components/BackdropLoading/index.js new file mode 100644 index 0000000..183b02b --- /dev/null +++ b/frontend/src/components/BackdropLoading/index.js @@ -0,0 +1,23 @@ +import React from "react"; + +import Backdrop from "@material-ui/core/Backdrop"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import { makeStyles } from "@material-ui/core/styles"; + +const useStyles = makeStyles(theme => ({ + backdrop: { + zIndex: theme.zIndex.drawer + 1, + color: "#fff", + }, +})); + +const BackdropLoading = () => { + const classes = useStyles(); + return ( + + + + ); +}; + +export default BackdropLoading; diff --git a/frontend/src/components/ButtonWithSpinner/index.js b/frontend/src/components/ButtonWithSpinner/index.js new file mode 100644 index 0000000..542c39c --- /dev/null +++ b/frontend/src/components/ButtonWithSpinner/index.js @@ -0,0 +1,35 @@ +import React from "react"; + +import { makeStyles } from "@material-ui/core/styles"; +import { green } from "@material-ui/core/colors"; +import { CircularProgress, Button } from "@material-ui/core"; + +const useStyles = makeStyles(theme => ({ + button: { + position: "relative", + }, + + buttonProgress: { + color: green[500], + position: "absolute", + top: "50%", + left: "50%", + marginTop: -12, + marginLeft: -12, + }, +})); + +const ButtonWithSpinner = ({ loading, children, ...rest }) => { + const classes = useStyles(); + + return ( + + ); +}; + +export default ButtonWithSpinner; diff --git a/frontend/src/components/CampaignModal/index.js b/frontend/src/components/CampaignModal/index.js new file mode 100644 index 0000000..4616e58 --- /dev/null +++ b/frontend/src/components/CampaignModal/index.js @@ -0,0 +1,771 @@ +import React, { useContext, useEffect, useRef, useState } from "react"; + +import { Field, Form, Formik } from "formik"; +import { head } from "lodash"; +import { toast } from "react-toastify"; +import * as Yup from "yup"; + +import Button from "@material-ui/core/Button"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import IconButton from "@material-ui/core/IconButton"; +import TextField from "@material-ui/core/TextField"; +import { green } from "@material-ui/core/colors"; +import { makeStyles } from "@material-ui/core/styles"; +import AttachFileIcon from "@material-ui/icons/AttachFile"; +import DeleteOutlineIcon from "@material-ui/icons/DeleteOutline"; + +import moment from "moment"; +import { i18n } from "../../translate/i18n"; + +import { + Box, + FormControl, + Grid, + InputLabel, + MenuItem, + Select, + Tab, + Tabs, +} from "@material-ui/core"; +import { AuthContext } from "../../context/Auth/AuthContext"; +import toastError from "../../errors/toastError"; +import api from "../../services/api"; +import ConfirmationModal from "../ConfirmationModal"; + +const useStyles = makeStyles((theme) => ({ + root: { + display: "flex", + flexWrap: "wrap", + backgroundColor: "#fff" + }, + + tabmsg: { + backgroundColor: theme.palette.campaigntab, + }, + + textField: { + marginRight: theme.spacing(1), + flex: 1, + }, + + extraAttr: { + display: "flex", + justifyContent: "center", + alignItems: "center", + }, + + btnWrapper: { + position: "relative", + }, + + buttonProgress: { + color: green[500], + position: "absolute", + top: "50%", + left: "50%", + marginTop: -12, + marginLeft: -12, + }, +})); + +const CampaignSchema = Yup.object().shape({ + name: Yup.string() + .min(2, "Too Short!") + .max(50, "Too Long!") + .required("Required"), +}); + +const CampaignModal = ({ + open, + onClose, + campaignId, + initialValues, + onSave, + resetPagination, +}) => { + const classes = useStyles(); + const isMounted = useRef(true); + const { user } = useContext(AuthContext); + const { companyId } = user; + const [file, setFile] = useState(null); + + const initialState = { + name: "", + message1: "", + message2: "", + message3: "", + message4: "", + message5: "", + confirmationMessage1: "", + confirmationMessage2: "", + confirmationMessage3: "", + confirmationMessage4: "", + confirmationMessage5: "", + status: "INATIVA", // INATIVA, PROGRAMADA, EM_ANDAMENTO, CANCELADA, FINALIZADA, + confirmation: false, + scheduledAt: "", + whatsappId: "", + contactListId: "", + tagListId: "Nenhuma", + companyId, + }; + + const [campaign, setCampaign] = useState(initialState); + const [whatsapps, setWhatsapps] = useState([]); + const [contactLists, setContactLists] = useState([]); + const [messageTab, setMessageTab] = useState(0); + const [attachment, setAttachment] = useState(null); + const [confirmationOpen, setConfirmationOpen] = useState(false); + const [campaignEditable, setCampaignEditable] = useState(true); + const attachmentFile = useRef(null); + const [tagLists, setTagLists] = useState([]); + + useEffect(() => { + return () => { + isMounted.current = false; + }; + }, []); + + useEffect(() => { + (async () => { + try { + const { data } = await api.get("/files/", { + params: { companyId } + }); + + setFile(data.files); + } catch (err) { + toastError(err); + } + })(); + }, []); + + useEffect(() => { + if (isMounted.current) { + if (initialValues) { + setCampaign((prevState) => { + return { ...prevState, ...initialValues }; + }); + } + + api + .get(`/contact-lists/list`, { params: { companyId } }) + .then(({ data }) => setContactLists(data)); + + api + .get(`/whatsapp`, { params: { companyId, session: 0 } }) + .then(({ data }) => setWhatsapps(data)); + + api.get(`/tags`, { params: { companyId } }) + .then(({ data }) => { + const fetchedTags = data.tags; + // Perform any necessary data transformation here + const formattedTagLists = fetchedTags.map((tag) => ({ + id: tag.id, + name: tag.name, + })); + setTagLists(formattedTagLists); + }) + .catch((error) => { + console.error("Error retrieving tags:", error); + }); + + if (!campaignId) return; + + api.get(`/campaigns/${campaignId}`).then(({ data }) => { + setCampaign((prev) => { + let prevCampaignData = Object.assign({}, prev); + + Object.entries(data).forEach(([key, value]) => { + if (key === "scheduledAt" && value !== "" && value !== null) { + prevCampaignData[key] = moment(value).format("YYYY-MM-DDTHH:mm"); + } else { + prevCampaignData[key] = value === null ? "" : value; + } + }); + + return prevCampaignData; + }); + }); + } + }, [campaignId, open, initialValues, companyId]); + + useEffect(() => { + const now = moment(); + const scheduledAt = moment(campaign.scheduledAt); + const moreThenAnHour = + !Number.isNaN(scheduledAt.diff(now)) && scheduledAt.diff(now, "hour") > 1; + const isEditable = + campaign.status === "INATIVA" || + (campaign.status === "PROGRAMADA" && moreThenAnHour); + + setCampaignEditable(isEditable); + }, [campaign.status, campaign.scheduledAt]); + + const handleClose = () => { + onClose(); + setCampaign(initialState); + }; + + const handleAttachmentFile = (e) => { + const file = head(e.target.files); + if (file) { + setAttachment(file); + } + }; + + const handleSaveCampaign = async (values) => { + try { + const dataValues = {}; + Object.entries(values).forEach(([key, value]) => { + if (key === "scheduledAt" && value !== "" && value !== null) { + dataValues[key] = moment(value).format("YYYY-MM-DD HH:mm:ss"); + } else { + dataValues[key] = value === "" ? null : value; + } + }); + + if (campaignId) { + await api.put(`/campaigns/${campaignId}`, dataValues); + + if (attachment != null) { + const formData = new FormData(); + formData.append("file", attachment); + await api.post(`/campaigns/${campaignId}/media-upload`, formData); + } + handleClose(); + } else { + const { data } = await api.post("/campaigns", dataValues); + + if (attachment != null) { + const formData = new FormData(); + formData.append("file", attachment); + await api.post(`/campaigns/${data.id}/media-upload`, formData); + } + if (onSave) { + onSave(data); + } + handleClose(); + } + toast.success(i18n.t("campaigns.toasts.success")); + } catch (err) { + console.log(err); + toastError(err); + } + }; + + const deleteMedia = async () => { + if (attachment) { + setAttachment(null); + attachmentFile.current.value = null; + } + + if (campaign.mediaPath) { + await api.delete(`/campaigns/${campaign.id}/media-upload`); + setCampaign((prev) => ({ ...prev, mediaPath: null, mediaName: null })); + toast.success(i18n.t("campaigns.toasts.deleted")); + } + }; + + const renderMessageField = (identifier) => { + return ( + + ); + }; + + const renderConfirmationMessageField = (identifier) => { + return ( + + ); + }; + + const cancelCampaign = async () => { + try { + await api.post(`/campaigns/${campaign.id}/cancel`); + toast.success(i18n.t("campaigns.toasts.cancel")); + setCampaign((prev) => ({ ...prev, status: "CANCELADA" })); + resetPagination(); + } catch (err) { + toast.error(err.message); + } + }; + + const restartCampaign = async () => { + try { + await api.post(`/campaigns/${campaign.id}/restart`); + toast.success(i18n.t("campaigns.toasts.restart")); + setCampaign((prev) => ({ ...prev, status: "EM_ANDAMENTO" })); + resetPagination(); + } catch (err) { + toast.error(err.message); + } + }; + + return ( +
+ setConfirmationOpen(false)} + onConfirm={deleteMedia} + > + {i18n.t("campaigns.confirmationModal.deleteMessage")} + + + + {campaignEditable ? ( + <> + {campaignId + ? `${i18n.t("campaigns.dialog.update")}` + : `${i18n.t("campaigns.dialog.new")}`} + + ) : ( + <>{`${i18n.t("campaigns.dialog.readonly")}`} + )} + +
+ handleAttachmentFile(e)} + /> +
+ { + setTimeout(() => { + handleSaveCampaign(values); + actions.setSubmitting(false); + }, 400); + }} + > + {({ values, errors, touched, isSubmitting }) => ( +
+ + + + + + {/* + + + {i18n.t("campaigns.dialog.form.confirmation")} + + + Desabilitada + Habilitada + + + */} + + + + {i18n.t("campaigns.dialog.form.contactList")} + + + Nenhuma + {contactLists && + contactLists.map((contactList) => ( + + {contactList.name} + + ))} + + + + + + + {i18n.t("campaigns.dialog.form.tagList")} + + + Nenhuma + {Array.isArray(tagLists) && + tagLists.map((tagList) => ( + + {tagList.name} + + ))} + + + + + + + {i18n.t("campaigns.dialog.form.whatsapp")} + + + Nenhuma + {whatsapps && + whatsapps.map((whatsapp) => ( + + {whatsapp.name} + + ))} + + + + + + + + + {i18n.t("campaigns.dialog.form.fileList")} + + {"Nenhum"} + {file.map(f => ( + + {f.name} + + ))} + + + + + setMessageTab(v)} + variant="fullWidth" + centered + style={{ + borderRadius: 2, + }} + > + + + + + + + + {messageTab === 0 && ( + <> + {values.confirmation ? ( + + + <>{renderMessageField("message1")} + + + <> + {renderConfirmationMessageField( + "confirmationMessage1" + )} + + + + ) : ( + <>{renderMessageField("message1")} + )} + + )} + {messageTab === 1 && ( + <> + {values.confirmation ? ( + + + <>{renderMessageField("message2")} + + + <> + {renderConfirmationMessageField( + "confirmationMessage2" + )} + + + + ) : ( + <>{renderMessageField("message2")} + )} + + )} + {messageTab === 2 && ( + <> + {values.confirmation ? ( + + + <>{renderMessageField("message3")} + + + <> + {renderConfirmationMessageField( + "confirmationMessage3" + )} + + + + ) : ( + <>{renderMessageField("message3")} + )} + + )} + {messageTab === 3 && ( + <> + {values.confirmation ? ( + + + <>{renderMessageField("message4")} + + + <> + {renderConfirmationMessageField( + "confirmationMessage4" + )} + + + + ) : ( + <>{renderMessageField("message4")} + )} + + )} + {messageTab === 4 && ( + <> + {values.confirmation ? ( + + + <>{renderMessageField("message5")} + + + <> + {renderConfirmationMessageField( + "confirmationMessage5" + )} + + + + ) : ( + <>{renderMessageField("message5")} + )} + + )} + + + {(campaign.mediaPath || attachment) && ( + + + {campaignEditable && ( + setConfirmationOpen(true)} + color="secondary" + > + + + )} + + )} + + + + {campaign.status === "CANCELADA" && ( + + )} + {campaign.status === "EM_ANDAMENTO" && ( + + )} + {!attachment && !campaign.mediaPath && campaignEditable && ( + + )} + + {(campaignEditable || campaign.status === "CANCELADA") && ( + + )} + +
+ )} +
+
+
+ ); +}; + +export default CampaignModal; diff --git a/frontend/src/components/Can/index.js b/frontend/src/components/Can/index.js new file mode 100644 index 0000000..3d80215 --- /dev/null +++ b/frontend/src/components/Can/index.js @@ -0,0 +1,39 @@ +import rules from "../../rules"; + +const check = (role, action, data) => { + const permissions = rules[role]; + if (!permissions) { + // role is not present in the rules + return false; + } + + const staticPermissions = permissions.static; + + if (staticPermissions && staticPermissions.includes(action)) { + // static rule not provided for action + return true; + } + + const dynamicPermissions = permissions.dynamic; + + if (dynamicPermissions) { + const permissionCondition = dynamicPermissions[action]; + if (!permissionCondition) { + // dynamic rule not provided for action + return false; + } + + return permissionCondition(data); + } + return false; +}; + +const Can = ({ role, perform, data, yes, no }) => + check(role, perform, data) ? yes() : no(); + +Can.defaultProps = { + yes: () => null, + no: () => null, +}; + +export { Can }; diff --git a/frontend/src/components/CheckoutPage/CheckoutPage.js b/frontend/src/components/CheckoutPage/CheckoutPage.js new file mode 100644 index 0000000..7e94b2c --- /dev/null +++ b/frontend/src/components/CheckoutPage/CheckoutPage.js @@ -0,0 +1,174 @@ +import React, { useContext, useState } from "react"; +import { + Stepper, + Step, + StepLabel, + Button, + Typography, + CircularProgress, +} from "@material-ui/core"; +import { Formik, Form } from "formik"; + +import AddressForm from "./Forms/AddressForm"; +import PaymentForm from "./Forms/PaymentForm"; +import ReviewOrder from "./ReviewOrder"; +import CheckoutSuccess from "./CheckoutSuccess"; + +import api from "../../services/api"; +import toastError from "../../errors/toastError"; +import { toast } from "react-toastify"; +import { AuthContext } from "../../context/Auth/AuthContext"; + + +import validationSchema from "./FormModel/validationSchema"; +import checkoutFormModel from "./FormModel/checkoutFormModel"; +import formInitialValues from "./FormModel/formInitialValues"; + +import useStyles from "./styles"; +import Invoices from "../../pages/Financeiro"; + + +export default function CheckoutPage(props) { + const steps = ["Dados", "Personalizar", "Revisar"]; + const { formId, formField } = checkoutFormModel; + + + + const classes = useStyles(); + const [activeStep, setActiveStep] = useState(1); + const [datePayment, setDatePayment] = useState(null); + const [invoiceId, setinvoiceId] = useState(props.Invoice.id); + const currentValidationSchema = validationSchema[activeStep]; + const isLastStep = activeStep === steps.length - 1; + const { user } = useContext(AuthContext); + +function _renderStepContent(step, setFieldValue, setActiveStep, values ) { + + switch (step) { + case 0: + return ; + case 1: + return ; + case 2: + return ; + default: + return
Not Found
; + } +} + + + async function _submitForm(values, actions) { + try { + const plan = JSON.parse(values.plan); + const newValues = { + firstName: values.firstName, + lastName: values.lastName, + address2: values.address2, + city: values.city, + state: values.state, + zipcode: values.zipcode, + country: values.country, + useAddressForPaymentDetails: values.useAddressForPaymentDetails, + nameOnCard: values.nameOnCard, + cardNumber: values.cardNumber, + cvv: values.cvv, + plan: values.plan, + price: plan.price, + users: plan.users, + connections: plan.connections, + invoiceId: invoiceId + } + + const { data } = await api.post("/subscription", newValues); + setDatePayment(data) + actions.setSubmitting(false); + setActiveStep(activeStep + 1); + toast.success("Assinatura realizada com sucesso!, aguardando a realização do pagamento"); + } catch (err) { + toastError(err); + } + } + + function _handleSubmit(values, actions) { + if (isLastStep) { + _submitForm(values, actions); + } else { + setActiveStep(activeStep + 1); + actions.setTouched({}); + actions.setSubmitting(false); + } + } + + function _handleBack() { + setActiveStep(activeStep - 1); + } + + return ( + + + Falta pouco! + + + {steps.map((label) => ( + + {label} + + ))} + + + {activeStep === steps.length ? ( + + ) : ( + + {({ isSubmitting, setFieldValue, values }) => ( +
+ {_renderStepContent(activeStep, setFieldValue, setActiveStep, values)} + +
+ {activeStep !== 1 && ( + + )} +
+ {activeStep !== 1 && ( + + )} + {isSubmitting && ( + + )} +
+
+
+ )} +
+ )} +
+
+ ); +} diff --git a/frontend/src/components/CheckoutPage/CheckoutSuccess/CheckoutSuccess.js b/frontend/src/components/CheckoutPage/CheckoutSuccess/CheckoutSuccess.js new file mode 100644 index 0000000..a2b9094 --- /dev/null +++ b/frontend/src/components/CheckoutPage/CheckoutSuccess/CheckoutSuccess.js @@ -0,0 +1,76 @@ +import React, { useState, useEffect, useContext } from 'react'; +import { useHistory } from "react-router-dom"; +import QRCode from 'react-qr-code'; +import { SuccessContent, Total } from './style'; +import { CopyToClipboard } from 'react-copy-to-clipboard'; +import { FaCopy, FaCheckCircle } from 'react-icons/fa'; +import { SocketContext } from "../../../context/Socket/SocketContext"; +import { useDate } from "../../../hooks/useDate"; +import { toast } from "react-toastify"; + +function CheckoutSuccess(props) { + + const { pix } = props; + const [pixString,] = useState(pix.qrcode.qrcode); + const [copied, setCopied] = useState(false); + const history = useHistory(); + + const { dateToClient } = useDate(); + + const socketManager = useContext(SocketContext); + + useEffect(() => { + const companyId = localStorage.getItem("companyId"); + const socket = socketManager.getSocket(companyId); + + socket.on(`company-${companyId}-payment`, (data) => { + + if (data.action === "CONCLUIDA") { + toast.success(`Sua licença foi renovada até ${dateToClient(data.company.dueDate)}!`); + setTimeout(() => { + history.push("/"); + }, 4000); + } + }); + }, [history, socketManager]); + + const handleCopyQR = () => { + setTimeout(() => { + setCopied(false); + }, 1 * 1000); + setCopied(true); + }; + + return ( + + + TOTAL + R${pix.valor.original.toLocaleString('pt-br', { minimumFractionDigits: 2 })} + + + + + + + + Para finalizar, basta realizar o pagamento escaneando ou colando o + código Pix acima :) + + + + ); +} + +export default CheckoutSuccess; diff --git a/frontend/src/components/CheckoutPage/CheckoutSuccess/index.js b/frontend/src/components/CheckoutPage/CheckoutSuccess/index.js new file mode 100644 index 0000000..32bd128 --- /dev/null +++ b/frontend/src/components/CheckoutPage/CheckoutSuccess/index.js @@ -0,0 +1,2 @@ +import CheckoutSuccess from './CheckoutSuccess'; +export default CheckoutSuccess; diff --git a/frontend/src/components/CheckoutPage/CheckoutSuccess/style.js b/frontend/src/components/CheckoutPage/CheckoutSuccess/style.js new file mode 100644 index 0000000..f0bbdee --- /dev/null +++ b/frontend/src/components/CheckoutPage/CheckoutSuccess/style.js @@ -0,0 +1,117 @@ +import styled from 'styled-components'; + +export const Container = styled.div` + footer { + margin-top: 30px; + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + + @media (max-width: 768px) { + flex-direction: column; + .checkout-buttons { + display: flex; + flex-direction: column-reverse; + width: 100%; + + button { + width: 100%; + margin-top: 16px; + margin-left: 0; + } + } + } + + button { + margin-left: 16px; + } + } +`; +export const Total = styled.div` + display: flex; + align-items: baseline; + + span { + color: #333; + font-weight: bold; + } + + strong { + color: #333; + font-size: 28px; + margin-left: 5px; + } + + @media (max-width: 768px) { + min-width: 100%; + justify-content: space-between; + } +`; + +export const SuccessContent = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + > h2 { + text-align: center; + } + + > svg { + margin-top: 16px; + } + + > span { + margin-top: 24px; + text-align: center; + } + + > p, + strong { + margin-top: 8px; + font-size: 9px; + color: #999; + } + + .copy-button { + font-size: 14px; + cursor: pointer; + text-align: center; + user-select: none; + min-height: 56px; + display: inline-flex; + -webkit-box-pack: center; + justify-content: center; + -webkit-box-align: center; + align-items: center; + background-color: #f9f9f9; + color: #000; + -webkit-appearance: none !important; + outline: none; + margin-top: 16px; + width: 256px; + font-weight: 600; + text-transform: uppercase; + border: none; + + > span { + margin-right: 8px; + } + } +`; + +export const CheckoutWrapper = styled.div` + width: 100%; + margin: 0 auto 0; + max-width: 1110px; + display: flex; + flex-direction: column; + -webkit-box-align: center; + align-items: center; + padding: 50px 95px; + background: #fff; + @media (max-width: 768px) { + padding: 16px 24px; +`; \ No newline at end of file diff --git a/frontend/src/components/CheckoutPage/FormModel/checkoutFormModel.js b/frontend/src/components/CheckoutPage/FormModel/checkoutFormModel.js new file mode 100644 index 0000000..f77ff4e --- /dev/null +++ b/frontend/src/components/CheckoutPage/FormModel/checkoutFormModel.js @@ -0,0 +1,73 @@ +export default { + formId: 'checkoutForm', + formField: { + firstName: { + name: 'firstName', + label: 'Nome completo*', + requiredErrorMsg: 'O nome completo é obrigatório' + }, + lastName: { + name: 'lastName', + label: 'Last name*', + requiredErrorMsg: 'Last name is required' + }, + address1: { + name: 'address2', + label: 'Endereço*', + requiredErrorMsg: 'O Endereço é obrigatório' + }, + + city: { + name: 'city', + label: 'Cidade*', + requiredErrorMsg: 'Cidade é obrigatória' + }, + state: { + name: 'state', + label: 'Estado*', + requiredErrorMsg: 'Cidade é obrigatória' + }, + zipcode: { + name: 'zipcode', + label: 'CEP*', + requiredErrorMsg: 'CEP é obrigatório', + invalidErrorMsg: 'Formato de CEP inválido' + }, + country: { + name: 'country', + label: 'País*', + requiredErrorMsg: 'País é obrigatório' + }, + useAddressForPaymentDetails: { + name: 'useAddressForPaymentDetails', + label: 'Use this address for payment details' + }, + invoiceId: { + name: 'invoiceId', + label: 'Use this invoiceId' + }, + nameOnCard: { + name: 'nameOnCard', + label: 'Name on card*', + requiredErrorMsg: 'Name on card is required' + }, + cardNumber: { + name: 'cardNumber', + label: 'Card number*', + requiredErrorMsg: 'Card number is required', + invalidErrorMsg: 'Card number is not valid (e.g. 4111111111111)' + }, + expiryDate: { + name: 'expiryDate', + label: 'Expiry date*', + requiredErrorMsg: 'Expiry date is required', + invalidErrorMsg: 'Expiry date is not valid' + }, + cvv: { + name: 'cvv', + label: 'CVV*', + requiredErrorMsg: 'CVV is required', + invalidErrorMsg: 'CVV is invalid (e.g. 357)' + } + } +}; diff --git a/frontend/src/components/CheckoutPage/FormModel/formInitialValues.js b/frontend/src/components/CheckoutPage/FormModel/formInitialValues.js new file mode 100644 index 0000000..a4d22e1 --- /dev/null +++ b/frontend/src/components/CheckoutPage/FormModel/formInitialValues.js @@ -0,0 +1,32 @@ +import checkoutFormModel from './checkoutFormModel'; +const { + formField: { + firstName, + lastName, + address1, + city, + state, + zipcode, + country, + useAddressForPaymentDetails, + nameOnCard, + cardNumber, + invoiceId, + cvv + } +} = checkoutFormModel; + +export default { + [firstName.name]: '', + [lastName.name]: '', + [address1.name]: '', + [city.name]: '', + [state.name]: '', + [zipcode.name]: '', + [country.name]: '', + [useAddressForPaymentDetails.name]: false, + [nameOnCard.name]: '', + [cardNumber.name]: '', + [invoiceId.name]: '', + [cvv.name]: '' +}; diff --git a/frontend/src/components/CheckoutPage/FormModel/validationSchema.js b/frontend/src/components/CheckoutPage/FormModel/validationSchema.js new file mode 100644 index 0000000..9c01534 --- /dev/null +++ b/frontend/src/components/CheckoutPage/FormModel/validationSchema.js @@ -0,0 +1,29 @@ +import * as Yup from 'yup'; +import checkoutFormModel from './checkoutFormModel'; +const { + formField: { + firstName, + address1, + city, + zipcode, + country, + } +} = checkoutFormModel; + + +export default [ + Yup.object().shape({ + [firstName.name]: Yup.string().required(`${firstName.requiredErrorMsg}`), + [address1.name]: Yup.string().required(`${address1.requiredErrorMsg}`), + [city.name]: Yup.string() + .nullable() + .required(`${city.requiredErrorMsg}`), + [zipcode.name]: Yup.string() + .required(`${zipcode.requiredErrorMsg}`), + + [country.name]: Yup.string() + .nullable() + .required(`${country.requiredErrorMsg}`) + }), + +]; diff --git a/frontend/src/components/CheckoutPage/Forms/AddressForm.js b/frontend/src/components/CheckoutPage/Forms/AddressForm.js new file mode 100644 index 0000000..a5afc16 --- /dev/null +++ b/frontend/src/components/CheckoutPage/Forms/AddressForm.js @@ -0,0 +1,134 @@ +import React, { useContext, useEffect, useState } from "react"; +import { Grid, Typography } from "@material-ui/core"; +import { InputField, SelectField } from "../../FormFields"; +import { AuthContext } from "../../../context/Auth/AuthContext"; + +const countries = [ + { + value: "BR", + label: "Brasil", + }, + { + value: "usa", + label: "United States", + }, +]; + +export default function AddressForm(props) { + + const { user } = useContext(AuthContext); + const [billingName, setBillingName] = useState(user.company.billingName); + const [addressZipCode, setAddressZipCode] = useState(user.company.addressZipCode); + const [addressStreet, setAddressStreet] = useState(user.company.addressStreet); + const [addressState, setAddressState] = useState(user.company.addressState); + const [addressCity, setAddressCity] = useState(user.company.addressCity); + const [addressDistrict, setAddressDistrict] = useState(user.company.addressDistrict); + + const { + formField: { + firstName, + address1, + city, + state, + zipcode, + country, + }, + setFieldValue + } = props; + useEffect(() => { + setFieldValue("firstName", billingName) + setFieldValue("zipcode", addressZipCode) + setFieldValue("address2", addressStreet) + setFieldValue("state", addressState) + setFieldValue("city", addressCity) + setFieldValue("country", addressDistrict) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + return ( + + + Vamos precisar de algumas informações + + + + + { + setBillingName(e.target.value) + setFieldValue("firstName", e.target.value) + }} + /> + + + { + setAddressDistrict(e.target.value) + setFieldValue("country", e.target.value) + } + } + /> + + + + { + setAddressZipCode(e.target.value) + setFieldValue("zipcode", e.target.value) + }} + /> + + + { + setAddressStreet(e.target.value) + setFieldValue("address2", e.target.value) + + }} + /> + + + + { + setAddressState(e.target.value) + setFieldValue("state", e.target.value) + + }} + /> + + + { + setAddressCity(e.target.value) + setFieldValue("city", e.target.value) + }} + /> + + + + + ); +} diff --git a/frontend/src/components/CheckoutPage/Forms/PaymentForm.js b/frontend/src/components/CheckoutPage/Forms/PaymentForm.js new file mode 100644 index 0000000..4a8a6f3 --- /dev/null +++ b/frontend/src/components/CheckoutPage/Forms/PaymentForm.js @@ -0,0 +1,237 @@ +import React, { useState, useEffect, useReducer } from 'react'; +import Button from '@material-ui/core/Button'; +import Card from '@material-ui/core/Card'; +import CardActions from '@material-ui/core/CardActions'; +import CardContent from '@material-ui/core/CardContent'; +import CardHeader from '@material-ui/core/CardHeader'; +import Grid from '@material-ui/core/Grid'; +import StarIcon from '@material-ui/icons/StarBorder'; +import Typography from '@material-ui/core/Typography'; +import { makeStyles } from '@material-ui/core/styles'; + +import IconButton from '@material-ui/core/IconButton'; +import MinimizeIcon from '@material-ui/icons/Minimize'; +import AddIcon from '@material-ui/icons/Add'; + +import usePlans from "../../../hooks/usePlans"; +import useCompanies from "../../../hooks/useCompanies"; + +const useStyles = makeStyles((theme) => ({ + '@global': { + ul: { + margin: 0, + padding: 0, + listStyle: 'none', + }, + }, + margin: { + margin: theme.spacing(1), + }, + + + cardHeader: { + backgroundColor: + theme.palette.type === 'light' ? theme.palette.grey[200] : theme.palette.grey[700], + }, + cardPricing: { + display: 'flex', + justifyContent: 'center', + alignItems: 'baseline', + marginBottom: theme.spacing(2), + }, + footer: { + borderTop: `1px solid ${theme.palette.divider}`, + marginTop: theme.spacing(8), + paddingTop: theme.spacing(3), + paddingBottom: theme.spacing(3), + [theme.breakpoints.up('sm')]: { + paddingTop: theme.spacing(6), + paddingBottom: theme.spacing(6), + }, + }, + + customCard: { + display: "flex", + marginTop: "16px", + alignItems: "center", + flexDirection: "column", + }, + custom: { + display: "flex", + alignItems: "center", + justifyContent: "space-between", + } +})); + + +export default function Pricing(props) { + const { + setFieldValue, + setActiveStep, + activeStep, + } = props; + + const handleChangeAdd = (event, newValue) => { + if (newValue < 3) return + + const newPrice = 11.00; + + setUsersPlans(newValue); + setCustomValuePlans(customValuePlans + newPrice); + } + + const handleChangeMin = (event, newValue) => { + if (newValue < 3) return + + const newPrice = 11; + + setUsersPlans(newValue); + setCustomValuePlans(customValuePlans - newPrice); + } + + const handleChangeConnectionsAdd = (event, newValue) => { + if (newValue < 3) return + const newPrice = 20.00; + setConnectionsPlans(newValue); + setCustomValuePlans(customValuePlans + newPrice); + } + + const handleChangeConnectionsMin = (event, newValue) => { + if (newValue < 3) return + const newPrice = 20; + setConnectionsPlans(newValue); + setCustomValuePlans(customValuePlans - newPrice); + } + + const { list, finder } = usePlans(); + const { find } = useCompanies(); + + const classes = useStyles(); + const [usersPlans, setUsersPlans] = React.useState(3); + const [companiesPlans, setCompaniesPlans] = useState(0); + const [connectionsPlans, setConnectionsPlans] = React.useState(3); + const [storagePlans, setStoragePlans] = React.useState([]); + const [customValuePlans, setCustomValuePlans] = React.useState(49.00); + const [loading, setLoading] = React.useState(false); + const companyId = localStorage.getItem("companyId"); + + useEffect(() => { + async function fetchData() { + await loadCompanies(); + } + fetchData(); + }, []) + + const loadCompanies = async () => { + setLoading(true); + try { + const companiesList = await find(companyId); + setCompaniesPlans(companiesList.planId); + await loadPlans(companiesList.planId); + } catch (e) { + console.log(e); + // toast.error("Não foi possível carregar a lista de registros"); + } + setLoading(false); + }; + const loadPlans = async (companiesPlans) => { + setLoading(true); + try { + const plansCompanies = await finder(companiesPlans); + const plans = [] + + //plansCompanies.forEach((plan) => { + plans.push({ + title: plansCompanies.name, + planId: plansCompanies.id, + price: plansCompanies.value, + description: [ + `${plansCompanies.users} Usuários`, + `${plansCompanies.connections} Conexão`, + `${plansCompanies.queues} Filas` + ], + users: plansCompanies.users, + connections: plansCompanies.connections, + queues: plansCompanies.queues, + buttonText: 'SELECIONAR', + buttonVariant: 'outlined', + }) + + // setStoragePlans(data); + //}); + setStoragePlans(plans); + } catch (e) { + console.log(e); + // toast.error("Não foi possível carregar a lista de registros"); + } + setLoading(false); + }; + + + const tiers = storagePlans + return ( + + + {tiers.map((tier) => ( + // Enterprise card is full width at sm breakpoint + + + : null} + className={classes.cardHeader} + /> + +
+ + { + + + R${tier.price.toLocaleString('pt-br', { minimumFractionDigits: 2 })} + + } + + + /mês + +
+
    + {tier.description.map((line) => ( + + {line} + + ))} +
+
+ + + +
+
+ ))} +
+
+ ); +} \ No newline at end of file diff --git a/frontend/src/components/CheckoutPage/ReviewOrder/PaymentDetails.js b/frontend/src/components/CheckoutPage/ReviewOrder/PaymentDetails.js new file mode 100644 index 0000000..8f7fa76 --- /dev/null +++ b/frontend/src/components/CheckoutPage/ReviewOrder/PaymentDetails.js @@ -0,0 +1,61 @@ +import React, {useContext} from 'react'; +import { Typography, Grid } from '@material-ui/core'; +import useStyles from './styles'; +import { AuthContext } from "../../../context/Auth/AuthContext"; + +function PaymentDetails(props) { + const { formValues } = props; + const classes = useStyles(); + const { firstName, address2, city, zipcode, state, country, plan } = formValues; + const { user } = useContext(AuthContext); + + + const newPlan = JSON.parse(plan); + const { price } = newPlan; + + return ( + + + Informação de pagamento + + + + + Email: + + + {user.company.email} + + + + + Nome: + + + {firstName} + + + + + Endereço: + + + + {address2}, {city} - {state} {zipcode} {country} + + + + + + Total: + + + R${price.toLocaleString('pt-br', {minimumFractionDigits: 2})} + + + + + ); +} + +export default PaymentDetails; diff --git a/frontend/src/components/CheckoutPage/ReviewOrder/ProductDetails.js b/frontend/src/components/CheckoutPage/ReviewOrder/ProductDetails.js new file mode 100644 index 0000000..6d9da8d --- /dev/null +++ b/frontend/src/components/CheckoutPage/ReviewOrder/ProductDetails.js @@ -0,0 +1,33 @@ +import React from 'react'; +import { Typography, List, ListItem, ListItemText } from '@material-ui/core'; +import useStyles from './styles'; + +const products = [ + { name: 'Product 1', desc: 'A nice thing', price: '$9.99' }, + { name: 'Product 2', desc: 'Another thing', price: '$3.45' }, + { name: 'Product 3', desc: 'Something else', price: '$6.51' }, + { name: 'Product 4', desc: 'Best thing of all', price: '$14.11' }, + { name: 'Shipping', desc: '', price: 'Free' } +]; + +function ProductDetails() { + const classes = useStyles(); + return ( + + {products.map(product => ( + + + {product.price} + + ))} + + + + $34.06 + + + + ); +} + +export default ProductDetails; diff --git a/frontend/src/components/CheckoutPage/ReviewOrder/ReviewOrder.js b/frontend/src/components/CheckoutPage/ReviewOrder/ReviewOrder.js new file mode 100644 index 0000000..4ffb132 --- /dev/null +++ b/frontend/src/components/CheckoutPage/ReviewOrder/ReviewOrder.js @@ -0,0 +1,19 @@ +import React from 'react'; +import { useFormikContext } from 'formik'; +import { Typography, Grid } from '@material-ui/core'; +import ShippingDetails from './ShippingDetails'; +import PaymentDetails from './PaymentDetails'; + +export default function ReviewOrder() { + const { values: formValues } = useFormikContext(); + return ( + + + Resumo da assinatura + + + + + + ); +} diff --git a/frontend/src/components/CheckoutPage/ReviewOrder/ShippingDetails.js b/frontend/src/components/CheckoutPage/ReviewOrder/ShippingDetails.js new file mode 100644 index 0000000..78c9de0 --- /dev/null +++ b/frontend/src/components/CheckoutPage/ReviewOrder/ShippingDetails.js @@ -0,0 +1,25 @@ +import React from 'react'; +import { Typography, Grid } from '@material-ui/core'; +import useStyles from './styles'; + +function PaymentDetails(props) { + const { formValues } = props; + const classes = useStyles(); + const { plan } = formValues; + + const newPlan = JSON.parse(plan); + const { users, connections, price } = newPlan; + return ( + + + Detalhes do plano + + Usuários: {users} + Whatsapps: {connections} + Cobrança: Mensal + Total: R${price.toLocaleString('pt-br', {minimumFractionDigits: 2})} + + ); +} + +export default PaymentDetails; diff --git a/frontend/src/components/CheckoutPage/ReviewOrder/index.js b/frontend/src/components/CheckoutPage/ReviewOrder/index.js new file mode 100644 index 0000000..4a3afc8 --- /dev/null +++ b/frontend/src/components/CheckoutPage/ReviewOrder/index.js @@ -0,0 +1,2 @@ +import ReviewOrder from './ReviewOrder'; +export default ReviewOrder; diff --git a/frontend/src/components/CheckoutPage/ReviewOrder/styles.js b/frontend/src/components/CheckoutPage/ReviewOrder/styles.js new file mode 100644 index 0000000..626176a --- /dev/null +++ b/frontend/src/components/CheckoutPage/ReviewOrder/styles.js @@ -0,0 +1,12 @@ +import { makeStyles } from '@material-ui/core/styles'; +export default makeStyles(theme => ({ + listItem: { + padding: theme.spacing(1, 0) + }, + total: { + fontWeight: '700' + }, + title: { + marginTop: theme.spacing(2) + } +})); diff --git a/frontend/src/components/CheckoutPage/index.js b/frontend/src/components/CheckoutPage/index.js new file mode 100644 index 0000000..8728a02 --- /dev/null +++ b/frontend/src/components/CheckoutPage/index.js @@ -0,0 +1,2 @@ +import CheckoutPage from './CheckoutPage'; +export default CheckoutPage; diff --git a/frontend/src/components/CheckoutPage/styles.js b/frontend/src/components/CheckoutPage/styles.js new file mode 100644 index 0000000..963c4d2 --- /dev/null +++ b/frontend/src/components/CheckoutPage/styles.js @@ -0,0 +1,23 @@ +import { makeStyles } from '@material-ui/core/styles'; +export default makeStyles(theme => ({ + stepper: { + padding: theme.spacing(3, 0, 5) + }, + buttons: { + display: 'flex', + justifyContent: 'flex-end' + }, + button: { + marginTop: theme.spacing(3), + marginLeft: theme.spacing(1) + }, + wrapper: { + margin: theme.spacing(1), + position: 'relative' + }, + buttonProgress: { + position: 'absolute', + top: '50%', + left: '50%' + } +})); diff --git a/frontend/src/components/ColorPicker/index.js b/frontend/src/components/ColorPicker/index.js new file mode 100644 index 0000000..7eb9d0a --- /dev/null +++ b/frontend/src/components/ColorPicker/index.js @@ -0,0 +1,85 @@ +import { Dialog } from "@material-ui/core"; +import React, { useState } from "react"; + +import { BlockPicker } from "react-color"; + +const ColorPicker = ({ onChange, currentColor, handleClose, open }) => { + const [selectedColor, setSelectedColor] = useState(currentColor); + + const handleChange = color => { + setSelectedColor(color.hex); + handleClose(); + }; + + const colors = [ + "#B80000", + "#DB3E00", + "#FCCB00", + "#008B02", + "#006B76", + "#1273DE", + "#004DCF", + "#5300EB", + "#EB9694", + "#FAD0C3", + "#FEF3BD", + "#C1E1C5", + "#BEDADC", + "#C4DEF6", + "#BED3F3", + "#D4C4FB", + "#4D4D4D", + "#999999", + "#F44E3B", + "#FE9200", + "#FCDC00", + "#DBDF00", + "#A4DD00", + "#68CCCA", + "#73D8FF", + "#AEA1FF", + "#FDA1FF", + "#333333", + "#808080", + "#cccccc", + "#D33115", + "#E27300", + "#FCC400", + "#B0BC00", + "#68BC00", + "#16A5A5", + "#009CE0", + "#7B64FF", + "#FA28FF", + "#666666", + "#B3B3B3", + "#9F0500", + "#C45100", + "#FB9E00", + "#808900", + "#194D33", + "#0C797D", + "#0062B1", + "#653294", + "#AB149E", + ]; + + return ( + + onChange(color.hex)} + /> + + ); +}; + +export default ColorPicker; diff --git a/frontend/src/components/CompaniesManager/index.js b/frontend/src/components/CompaniesManager/index.js new file mode 100644 index 0000000..c3c4c08 --- /dev/null +++ b/frontend/src/components/CompaniesManager/index.js @@ -0,0 +1,632 @@ +import { + FormControl, + Grid, + IconButton, + InputLabel, + MenuItem, + Paper, + Select, + Table, + TableBody, + TableCell, + TableHead, + TableRow, + TextField, + makeStyles, +} from "@material-ui/core"; +import { Field, Form, Formik } from "formik"; +import React, { useEffect, useState } from "react"; +import ButtonWithSpinner from "../ButtonWithSpinner"; +import ConfirmationModal from "../ConfirmationModal"; + +import { Edit as EditIcon } from "@material-ui/icons"; + +import { has, head, isArray } from "lodash"; +import { toast } from "react-toastify"; +import useCompanies from "../../hooks/useCompanies"; +import { useDate } from "../../hooks/useDate"; +import usePlans from "../../hooks/usePlans"; +import api from "../../services/api"; +import ModalUsers from "../ModalUsers"; + +import moment from "moment"; + +const useStyles = makeStyles((theme) => ({ + root: { + width: "100%", + }, + mainPaper: { + width: "100%", + flex: 1, + padding: theme.spacing(2), + }, + fullWidth: { + width: "100%", + }, + tableContainer: { + width: "100%", + overflowX: "scroll", + ...theme.scrollbarStyles, + }, + textfield: { + width: "100%", + }, + textRight: { + textAlign: "right", + }, + row: { + paddingTop: theme.spacing(2), + paddingBottom: theme.spacing(2), + }, + control: { + paddingRight: theme.spacing(1), + paddingLeft: theme.spacing(1), + }, + buttonContainer: { + textAlign: "right", + padding: theme.spacing(1), + }, +})); + +export function CompanyForm(props) { + const { onSubmit, onDelete, onCancel, initialValue, loading } = props; + const classes = useStyles(); + const [plans, setPlans] = useState([]); + const [modalUser, setModalUser] = useState(false); + const [firstUser, setFirstUser] = useState({}); + + const [record, setRecord] = useState({ + id: "", + name: "", + email: "", + phone: "", + planId: "", + status: true, + //campaignsEnabled: false, + dueDate: "", + recurrence: "", + ...initialValue, + }); + + const { list: listPlans } = usePlans(); + + useEffect(() => { + async function fetchData() { + const list = await listPlans(); + setPlans(list); + } + fetchData(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + setRecord((prev) => { + if (moment(initialValue).isValid()) { + initialValue.dueDate = moment(initialValue.dueDate).format( + "YYYY-MM-DD" + ); + } + return { + ...prev, + ...initialValue, + }; + }); + }, [initialValue]); + + const handleSubmit = async (data) => { + if (data.dueDate === "" || moment(data.dueDate).isValid() === false) { + data.dueDate = null; + } + onSubmit(data); + setRecord({ ...initialValue, dueDate: "" }); + }; + + const handleOpenModalUsers = async () => { + try { + const { data } = await api.get("/users/list", { + params: { + companyId: initialValue.id, + }, + }); + if (isArray(data) && data.length) { + setFirstUser(head(data)); + } + setModalUser(true); + } catch (e) { + toast.error(e); + } + }; + + const handleCloseModalUsers = () => { + setFirstUser({}); + setModalUser(false); + }; + + const incrementDueDate = () => { + const data = { ...record }; + if (data.dueDate !== "" && data.dueDate !== null) { + switch (data.recurrence) { + case "MENSAL": + data.dueDate = moment(data.dueDate) + .add(1, "month") + .format("YYYY-MM-DD"); + break; + case "BIMESTRAL": + data.dueDate = moment(data.dueDate) + .add(2, "month") + .format("YYYY-MM-DD"); + break; + case "TRIMESTRAL": + data.dueDate = moment(data.dueDate) + .add(3, "month") + .format("YYYY-MM-DD"); + break; + case "SEMESTRAL": + data.dueDate = moment(data.dueDate) + .add(6, "month") + .format("YYYY-MM-DD"); + break; + case "ANUAL": + data.dueDate = moment(data.dueDate) + .add(12, "month") + .format("YYYY-MM-DD"); + break; + default: + break; + } + } + setRecord(data); + }; + + return ( + <> + + + setTimeout(() => { + handleSubmit(values); + resetForm(); + }, 500) + } + > + {(values, setValues) => ( +
+ + + + + + + + + + + + + Plano + + {plans.map((plan, key) => ( + + {plan.name} + + ))} + + + + + + Status + + Sim + Não + + + + {/* + + Campanhas + + Habilitadas + Desabilitadas + + + */} + + + + + + + + + Recorrência + + + Mensal + {/*Bimestral*/} + {/*Trimestral*/} + {/*Semestral*/} + {/*Anual*/} + + + + + + + onCancel()} + variant="contained" + > + Limpar + + + {record.id !== undefined ? ( + <> + + onDelete(record)} + variant="contained" + color="secondary" + > + Excluir + + + + incrementDueDate()} + variant="contained" + color="primary" + > + + Vencimento + + + + handleOpenModalUsers()} + variant="contained" + color="primary" + > + Usuário + + + + ) : null} + + + Salvar + + + + + +
+ )} +
+ + ); +} + +export function CompaniesManagerGrid(props) { + const { records, onSelect } = props; + const classes = useStyles(); + const { dateToClient } = useDate(); + + const renderStatus = (row) => { + return row.status === false ? "Não" : "Sim"; + }; + + const renderPlan = (row) => { + return row.planId !== null ? row.plan.name : "-"; + }; + + {/*const renderCampaignsStatus = (row) => { + if ( + has(row, "settings") && + isArray(row.settings) && + row.settings.length > 0 + ) { + const setting = row.settings.find((s) => s.key === "campaignsEnabled"); + if (setting) { + return setting.value === "true" ? "Habilitadas" : "Desabilitadas"; + } + } + return "Desabilitadas"; + };*/} + + const rowStyle = (record) => { + if (moment(record.dueDate).isValid()) { + const now = moment(); + const dueDate = moment(record.dueDate); + const diff = dueDate.diff(now, "days"); + if (diff >= 1 && diff <= 5) { + return { backgroundColor: "#fffead" }; + } + if (diff <= 0) { + return { backgroundColor: "#fa8c8c" }; + } + // else { + // return { backgroundColor: "#affa8c" }; + // } + } + return {}; + }; + + return ( + + + + + + # + + ID + Nome + E-mail + Telefone + Plano + {/*Campanhas*/} + Status + Criada Em + Vencimento + + + + {records.map((row, key) => ( + + + onSelect(row)} aria-label="delete"> + + + + {row.id || "-"} + {row.name || "-"} + {row.email || "-"} + {row.phone || "-"} + {renderPlan(row)} + {/*{renderCampaignsStatus(row)}*/} + {renderStatus(row)} + {dateToClient(row.createdAt)} + + {dateToClient(row.dueDate)} +
+ {row.recurrence} +
+
+ ))} +
+
+
+ ); +} + +export default function CompaniesManager() { + const classes = useStyles(); + const { list, save, update, remove } = useCompanies(); + + const [showConfirmDialog, setShowConfirmDialog] = useState(false); + const [loading, setLoading] = useState(false); + const [records, setRecords] = useState([]); + const [record, setRecord] = useState({ + id: "", + name: "", + email: "", + phone: "", + planId: "", + status: true, + //campaignsEnabled: false, + dueDate: "", + recurrence: "", + }); + + useEffect(() => { + loadPlans(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const loadPlans = async () => { + setLoading(true); + try { + const companyList = await list(); + setRecords(companyList); + } catch (e) { + toast.error("Não foi possível carregar a lista de registros"); + } + setLoading(false); + }; + + const handleSubmit = async (data) => { + setLoading(true); + try { + if (data.id !== undefined) { + await update(data); + } else { + await save(data); + } + await loadPlans(); + handleCancel(); + toast.success("Operação realizada com sucesso!"); + } catch (e) { + toast.error( + "Não foi possível realizar a operação. Verifique se já existe uma empresa com o mesmo nome ou se os campos foram preenchidos corretamente" + ); + } + setLoading(false); + }; + + const handleDelete = async () => { + setLoading(true); + try { + await remove(record.id); + await loadPlans(); + handleCancel(); + toast.success("Operação realizada com sucesso!"); + } catch (e) { + toast.error("Não foi possível realizar a operação"); + } + setLoading(false); + }; + + const handleOpenDeleteDialog = () => { + setShowConfirmDialog(true); + }; + + const handleCancel = () => { + setRecord((prev) => ({ + ...prev, + id: "", + name: "", + email: "", + phone: "", + planId: "", + status: true, + //campaignsEnabled: false, + dueDate: "", + recurrence: "", + })); + }; + + const handleSelect = (data) => { +// let campaignsEnabled = false; + +// const setting = data.settings.find( +// (s) => s.key.indexOf("campaignsEnabled") > -1 +// ); +// if (setting) { +// campaignsEnabled = +// setting.value === "true" || setting.value === "enabled"; +// } + + setRecord((prev) => ({ + ...prev, + id: data.id, + name: data.name || "", + phone: data.phone || "", + email: data.email || "", + planId: data.planId || "", + status: data.status === false ? false : true, + //campaignsEnabled, + dueDate: data.dueDate || "", + recurrence: data.recurrence || "", + })); + }; + + return ( + + + + + + + + + + setShowConfirmDialog(false)} + onConfirm={() => handleDelete()} + > + Deseja realmente excluir esse registro? + + + ); +} diff --git a/frontend/src/components/ConfirmationModal/index.js b/frontend/src/components/ConfirmationModal/index.js new file mode 100644 index 0000000..ce340f2 --- /dev/null +++ b/frontend/src/components/ConfirmationModal/index.js @@ -0,0 +1,45 @@ +import React from "react"; +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import Typography from "@material-ui/core/Typography"; + +import { i18n } from "../../translate/i18n"; + +const ConfirmationModal = ({ title, children, open, onClose, onConfirm }) => { + return ( + onClose(false)} + aria-labelledby="confirm-dialog" + > + {title} + + {children} + + + + + + + ); +}; + +export default ConfirmationModal; diff --git a/frontend/src/components/ContactDrawer/index.js b/frontend/src/components/ContactDrawer/index.js new file mode 100644 index 0000000..34e3e78 --- /dev/null +++ b/frontend/src/components/ContactDrawer/index.js @@ -0,0 +1,208 @@ +import React, { useEffect, useState } from "react"; + +import { makeStyles } from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import IconButton from "@material-ui/core/IconButton"; +import CloseIcon from "@material-ui/icons/Close"; +import Drawer from "@material-ui/core/Drawer"; +import Link from "@material-ui/core/Link"; +import InputLabel from "@material-ui/core/InputLabel"; +import Avatar from "@material-ui/core/Avatar"; +import Button from "@material-ui/core/Button"; +import Paper from "@material-ui/core/Paper"; +import CreateIcon from '@material-ui/icons/Create'; + +import { i18n } from "../../translate/i18n"; + +import ContactDrawerSkeleton from "../ContactDrawerSkeleton"; +import MarkdownWrapper from "../MarkdownWrapper"; +import { CardHeader } from "@material-ui/core"; +import { ContactForm } from "../ContactForm"; +import ContactModal from "../ContactModal"; +import { ContactNotes } from "../ContactNotes"; + +import { generateColor } from "../../helpers/colorGenerator"; +import { getInitials } from "../../helpers/getInitials"; + +const drawerWidth = 320; + +const useStyles = makeStyles(theme => ({ + drawer: { + width: drawerWidth, + flexShrink: 0, + }, + drawerPaper: { + width: drawerWidth, + display: "flex", + borderTop: "1px solid rgba(0, 0, 0, 0.12)", + borderRight: "1px solid rgba(0, 0, 0, 0.12)", + borderBottom: "1px solid rgba(0, 0, 0, 0.12)", + borderTopRightRadius: 4, + borderBottomRightRadius: 4, + }, + header: { + display: "flex", + borderBottom: "1px solid rgba(0, 0, 0, 0.12)", + backgroundColor: theme.palette.contactdrawer, //DARK MODE PLW DESIGN// + alignItems: "center", + padding: theme.spacing(0, 1), + minHeight: "73px", + justifyContent: "flex-start", + }, + content: { + display: "flex", + backgroundColor: theme.palette.contactdrawer, //DARK MODE PLW DESIGN// + flexDirection: "column", + padding: "8px 0px 8px 8px", + height: "100%", + overflowY: "scroll", + ...theme.scrollbarStyles, + }, + + contactAvatar: { + margin: 15, + width: 100, + height: 100, + }, + + contactHeader: { + display: "flex", + padding: 8, + flexDirection: "column", + alignItems: "center", + justifyContent: "center", + "& > *": { + margin: 4, + }, + }, + + contactDetails: { + marginTop: 8, + padding: 8, + display: "flex", + flexDirection: "column", + }, + contactExtraInfo: { + marginTop: 4, + padding: 6, + }, +})); + +const ContactDrawer = ({ open, handleDrawerClose, contact, ticket, loading }) => { + const classes = useStyles(); + + const [modalOpen, setModalOpen] = useState(false); + const [openForm, setOpenForm] = useState(false); + + useEffect(() => { + setOpenForm(false); + }, [open, contact]); + + return ( + <> + +
+ + + + + {i18n.t("contactDrawer.header")} + +
+ {loading ? ( + + ) : ( +
+ + {}} + style={{ cursor: "pointer", width: '100%' }} + titleTypographyProps={{ noWrap: true }} + subheaderTypographyProps={{ noWrap: true }} + avatar={ + {getInitials(contact?.name)} + } + title={ + <> + setOpenForm(true)}> + {contact.name} + + + + } + subheader={ + <> + + {contact.number} + + + {contact.email} + + + } + /> + + {(contact.id && openForm) && setOpenForm(false)} />} + + + + {i18n.t("ticketOptionsMenu.appointmentsModal.title")} + + + + + setModalOpen(false)} + contactId={contact.id} + > + + {i18n.t("contactDrawer.extraInfo")} + + {contact?.extraInfo?.map(info => ( + + {info.name} + + {info.value} + + + ))} + +
+ )} +
+ + ); +}; + +export default ContactDrawer; diff --git a/frontend/src/components/ContactDrawerSkeleton/index.js b/frontend/src/components/ContactDrawerSkeleton/index.js new file mode 100644 index 0000000..14b9027 --- /dev/null +++ b/frontend/src/components/ContactDrawerSkeleton/index.js @@ -0,0 +1,50 @@ +import React from "react"; +import Skeleton from "@material-ui/lab/Skeleton"; +import Typography from "@material-ui/core/Typography"; +import Paper from "@material-ui/core/Paper"; +import { i18n } from "../../translate/i18n"; +import { Grid } from "@material-ui/core"; + +const ContactDrawerSkeleton = ({ classes }) => { + return ( +
+ + + + + + + + + + + + + + + {i18n.t("contactDrawer.extraInfo")} + + + + + + + + + + + + + + +
+ ); +}; + +export default ContactDrawerSkeleton; diff --git a/frontend/src/components/ContactForm/index.js b/frontend/src/components/ContactForm/index.js new file mode 100644 index 0000000..efdc98a --- /dev/null +++ b/frontend/src/components/ContactForm/index.js @@ -0,0 +1,187 @@ +import React, { useState, useEffect } from "react"; + +import * as Yup from "yup"; +import { Formik, Form, Field } from "formik"; +import { toast } from "react-toastify"; + +import { makeStyles } from "@material-ui/core/styles"; +import { green } from "@material-ui/core/colors"; +import Button from "@material-ui/core/Button"; +import TextField from "@material-ui/core/TextField"; +import CircularProgress from "@material-ui/core/CircularProgress"; + +import { i18n } from "../../translate/i18n"; + +import api from "../../services/api"; +import toastError from "../../errors/toastError"; +import { Grid } from "@material-ui/core"; + +const useStyles = makeStyles(theme => ({ + root: { + display: "flex", + flexWrap: "wrap", + }, + textField: { + marginRight: theme.spacing(1), + flex: 1, + }, + + extraAttr: { + display: "flex", + justifyContent: "center", + alignItems: "center", + }, + + btnWrapper: { + position: "relative", + }, + + buttonProgress: { + color: green[500], + position: "absolute", + top: "50%", + left: "50%", + marginTop: -12, + marginLeft: -12, + }, + + textCenter: { + backgroundColor: 'red' + } +})); + +const ContactSchema = Yup.object().shape({ + name: Yup.string() + .min(2, "Too Short!") + .max(50, "Too Long!") + .required("Required"), + number: Yup.string().min(8, "Too Short!").max(50, "Too Long!"), + email: Yup.string().email("Invalid email"), +}); + +export function ContactForm ({ initialContact, onSave, onCancel }) { + const classes = useStyles(); + + const [contact, setContact] = useState(initialContact); + + useEffect(() => { + setContact(initialContact); + }, [initialContact]); + + const handleSaveContact = async values => { + try { + if (contact.id) { + await api.put(`/contacts/${contact.id}`, values); + } else { + const { data } = await api.post("/contacts", values); + if (onSave) { + onSave(data); + } + } + toast.success(i18n.t("contactModal.success")); + } catch (err) { + toastError(err); + } + }; + + return ( + { + setTimeout(() => { + handleSaveContact(values); + actions.setSubmitting(false); + }, 400); + }} + > + {({ values, errors, touched, isSubmitting }) => ( +
+ + {/* + + {i18n.t("contactModal.form.mainInfo")} + + */} + + + + + + + + + + + + + + + + + + + + +
+ )} +
+ ) +} diff --git a/frontend/src/components/ContactListDialog/index.js b/frontend/src/components/ContactListDialog/index.js new file mode 100644 index 0000000..de6ac3b --- /dev/null +++ b/frontend/src/components/ContactListDialog/index.js @@ -0,0 +1,181 @@ +import React, { useState, useEffect } from "react"; + +import * as Yup from "yup"; +import { Formik, Form, Field } from "formik"; +import { toast } from "react-toastify"; + +import { makeStyles } from "@material-ui/core/styles"; +import { green } from "@material-ui/core/colors"; +import Button from "@material-ui/core/Button"; +import TextField from "@material-ui/core/TextField"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import CircularProgress from "@material-ui/core/CircularProgress"; + +import { i18n } from "../../translate/i18n"; + +import api from "../../services/api"; +import toastError from "../../errors/toastError"; + +const useStyles = makeStyles((theme) => ({ + root: { + display: "flex", + flexWrap: "wrap", + }, + multFieldLine: { + display: "flex", + "& > *:not(:last-child)": { + marginRight: theme.spacing(1), + }, + }, + + btnWrapper: { + position: "relative", + }, + + buttonProgress: { + color: green[500], + position: "absolute", + top: "50%", + left: "50%", + marginTop: -12, + marginLeft: -12, + }, + formControl: { + margin: theme.spacing(1), + minWidth: 120, + }, +})); + +const ContactListSchema = Yup.object().shape({ + name: Yup.string() + .min(2, "Too Short!") + .max(50, "Too Long!") + .required("Required"), +}); + +const ContactListModal = ({ open, onClose, contactListId }) => { + const classes = useStyles(); + + const initialState = { + name: "", + }; + + const [contactList, setContactList] = useState(initialState); + + useEffect(() => { + const fetchContactList = async () => { + if (!contactListId) return; + try { + const { data } = await api.get(`/contact-lists/${contactListId}`); + setContactList((prevState) => { + return { ...prevState, ...data }; + }); + } catch (err) { + toastError(err); + } + }; + + fetchContactList(); + }, [contactListId, open]); + + const handleClose = () => { + onClose(); + setContactList(initialState); + }; + + const handleSaveContactList = async (values) => { + const contactListData = { ...values }; + try { + if (contactListId) { + await api.put(`/contact-lists/${contactListId}`, contactListData); + } else { + await api.post("/contact-lists", contactListData); + } + toast.success(i18n.t("contactList.dialog")); + } catch (err) { + toastError(err); + } + handleClose(); + }; + + return ( +
+ + + {contactListId + ? `${i18n.t("contactLists.dialog.edit")}` + : `${i18n.t("contactLists.dialog.add")}`} + + { + setTimeout(() => { + handleSaveContactList(values); + actions.setSubmitting(false); + }, 400); + }} + > + {({ touched, errors, isSubmitting }) => ( +
+ +
+ +
+
+ + + + +
+ )} +
+
+
+ ); +}; + +export default ContactListModal; diff --git a/frontend/src/components/ContactListItemModal/index.js b/frontend/src/components/ContactListItemModal/index.js new file mode 100644 index 0000000..52d3881 --- /dev/null +++ b/frontend/src/components/ContactListItemModal/index.js @@ -0,0 +1,242 @@ +import React, { useState, useEffect, useRef, useContext } from "react"; + +import * as Yup from "yup"; +import { Formik, Form, Field } from "formik"; +import { toast } from "react-toastify"; + +import { makeStyles } from "@material-ui/core/styles"; +import { green } from "@material-ui/core/colors"; +import Button from "@material-ui/core/Button"; +import TextField from "@material-ui/core/TextField"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import Typography from "@material-ui/core/Typography"; +import CircularProgress from "@material-ui/core/CircularProgress"; + +import { i18n } from "../../translate/i18n"; + +import api from "../../services/api"; +import toastError from "../../errors/toastError"; +import { useParams } from "react-router-dom"; +import { AuthContext } from "../../context/Auth/AuthContext"; + +const useStyles = makeStyles((theme) => ({ + root: { + display: "flex", + flexWrap: "wrap", + }, + textField: { + marginRight: theme.spacing(1), + flex: 1, + }, + + extraAttr: { + display: "flex", + justifyContent: "center", + alignItems: "center", + }, + + btnWrapper: { + position: "relative", + }, + + buttonProgress: { + color: green[500], + position: "absolute", + top: "50%", + left: "50%", + marginTop: -12, + marginLeft: -12, + }, +})); + +const ContactSchema = Yup.object().shape({ + name: Yup.string() + .min(2, "Too Short!") + .max(50, "Too Long!") + .required("Required"), + number: Yup.string().min(8, "Too Short!").max(50, "Too Long!"), + email: Yup.string().email("Invalid email"), +}); + +const ContactListItemModal = ({ + open, + onClose, + contactId, + initialValues, + onSave, +}) => { + const classes = useStyles(); + const isMounted = useRef(true); + + const { + user: { companyId }, + } = useContext(AuthContext); + const { contactListId } = useParams(); + + const initialState = { + name: "", + number: "", + email: "", + }; + + const [contact, setContact] = useState(initialState); + + useEffect(() => { + return () => { + isMounted.current = false; + }; + }, []); + + useEffect(() => { + const fetchContact = async () => { + if (initialValues) { + setContact((prevState) => { + return { ...prevState, ...initialValues }; + }); + } + + if (!contactId) return; + + try { + const { data } = await api.get(`/contact-list-items/${contactId}`); + if (isMounted.current) { + setContact(data); + } + } catch (err) { + toastError(err); + } + }; + + fetchContact(); + }, [contactId, open, initialValues]); + + const handleClose = () => { + onClose(); + setContact(initialState); + }; + + const handleSaveContact = async (values) => { + try { + if (contactId) { + await api.put(`/contact-list-items/${contactId}`, { + ...values, + companyId, + contactListId, + }); + handleClose(); + } else { + const { data } = await api.post("/contact-list-items", { + ...values, + companyId, + contactListId, + }); + if (onSave) { + onSave(data); + } + handleClose(); + } + toast.success(i18n.t("contactModal.success")); + } catch (err) { + toastError(err); + } + }; + + return ( +
+ + + {contactId + ? `${i18n.t("contactModal.title.edit")}` + : `${i18n.t("contactModal.title.add")}`} + + { + setTimeout(() => { + handleSaveContact(values); + actions.setSubmitting(false); + }, 400); + }} + > + {({ values, errors, touched, isSubmitting }) => ( +
+ + + {i18n.t("contactModal.form.mainInfo")} + + + +
+ +
+
+ + + + +
+ )} +
+
+
+ ); +}; + +export default ContactListItemModal; diff --git a/frontend/src/components/ContactListTable/index.js b/frontend/src/components/ContactListTable/index.js new file mode 100644 index 0000000..24f354d --- /dev/null +++ b/frontend/src/components/ContactListTable/index.js @@ -0,0 +1,103 @@ +import React, { useState, useEffect } from "react"; +import PropTypes from "prop-types"; +import { + Table, + TableHead, + TableBody, + TableCell, + TableRow, + IconButton, +} from "@material-ui/core"; +import { + Edit as EditIcon, + DeleteOutline as DeleteOutlineIcon, + People as PeopleIcon, +} from "@material-ui/icons"; + +import TableRowSkeleton from "../../components/TableRowSkeleton"; + +function ContactListsTable(props) { + const { + contactLists, + showLoading, + editContactList, + deleteContactList, + readOnly, + } = props; + const [loading, setLoading] = useState(true); + const [rows, setRows] = useState([]); + + useEffect(() => { + if (Array.isArray(contactLists)) { + setRows(contactLists); + } + if (showLoading !== undefined) { + setLoading(showLoading); + } + }, [contactLists, showLoading]); + + const handleEdit = (contactList) => { + editContactList(contactList); + }; + + const handleDelete = (contactList) => { + deleteContactList(contactList); + }; + + const renderRows = () => { + return rows.map((contactList) => { + return ( + + {contactList.name} + + {!readOnly ? ( + + + + + + handleEdit(contactList)}> + + + + handleDelete(contactList)} + > + + + + ) : null} + + ); + }); + }; + + return ( + + + + Nome + Contatos + {!readOnly ? Ações : null} + + + + {loading ? ( + + ) : ( + renderRows() + )} + +
+ ); +} + +ContactListsTable.propTypes = { + contactLists: PropTypes.array.isRequired, + showLoading: PropTypes.bool, + editContactList: PropTypes.func.isRequired, + deleteContactList: PropTypes.func.isRequired, +}; + +export default ContactListsTable; diff --git a/frontend/src/components/ContactModal/index.js b/frontend/src/components/ContactModal/index.js new file mode 100644 index 0000000..2ca2a9a --- /dev/null +++ b/frontend/src/components/ContactModal/index.js @@ -0,0 +1,304 @@ +import React, { useState, useEffect, useRef } from "react"; + +import * as Yup from "yup"; +import { Formik, FieldArray, Form, Field } from "formik"; +import { toast } from "react-toastify"; + +import { makeStyles } from "@material-ui/core/styles"; +import { green } from "@material-ui/core/colors"; +import Button from "@material-ui/core/Button"; +import TextField from "@material-ui/core/TextField"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import Typography from "@material-ui/core/Typography"; +import IconButton from "@material-ui/core/IconButton"; +import DeleteOutlineIcon from "@material-ui/icons/DeleteOutline"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import FormControlLabel from "@material-ui/core/FormControlLabel"; +import Switch from "@material-ui/core/Switch"; +import { i18n } from "../../translate/i18n"; + +import api from "../../services/api"; +import toastError from "../../errors/toastError"; + +const useStyles = makeStyles(theme => ({ + root: { + display: "flex", + flexWrap: "wrap", + }, + textField: { + marginRight: theme.spacing(1), + flex: 1, + }, + + extraAttr: { + display: "flex", + justifyContent: "center", + alignItems: "center", + }, + + btnWrapper: { + position: "relative", + }, + + buttonProgress: { + color: green[500], + position: "absolute", + top: "50%", + left: "50%", + marginTop: -12, + marginLeft: -12, + }, +})); + +/*const phoneRegExp = + /^((\\+[1-9]{1,4}[ \\-]*)|(\\([0-9]{2,3}\\)[ \\-]*)|([0-9]{2,4})[ \\-]*)*?[0-9]{3,4}?[ \\-]*[0-9]{3,4}?$/; +*/ +const ContactSchema = Yup.object().shape({ + name: Yup.string() + .min(2, "Too Short!") + .max(50, "Too Long!") + .required("Required"), + /*number: Yup.string() + .min(12, "Número inválido") + .max(16, "Número inválido") + .matches(phoneRegExp, "Número inválido") + .required("Informe o número"),*/ + email: Yup.string().email("Email inválido"), +}); + +const ContactModal = ({ open, onClose, contactId, initialValues, onSave }) => { + const classes = useStyles(); + const isMounted = useRef(true); + + const initialState = { + name: "", + number: "", + email: "", + disableBot: false + }; + + const [contact, setContact] = useState(initialState); + + useEffect(() => { + return () => { + isMounted.current = false; + }; + }, []); + + useEffect(() => { + const fetchContact = async () => { + if (initialValues) { + setContact(prevState => { + return { ...prevState, ...initialValues }; + }); + } + + if (!contactId) return; + + try { + const { data } = await api.get(`/contacts/${contactId}`); + if (isMounted.current) { + console.log(data) + setContact(data); + } + } catch (err) { + toastError(err); + } + }; + + fetchContact(); + }, [contactId, open, initialValues]); + + const handleClose = () => { + onClose(); + setContact(initialState); + }; + + const handleSaveContact = async values => { + try { + if (contactId) { + await api.put(`/contacts/${contactId}`, values); + handleClose(); + } else { + const { data } = await api.post("/contacts", values); + if (onSave) { + onSave(data); + } + handleClose(); + } + toast.success(i18n.t("contactModal.success")); + } catch (err) { + toastError(err); + } + }; + + return ( +
+ + + {contactId + ? `${i18n.t("contactModal.title.edit")}` + : `${i18n.t("contactModal.title.add")}`} + + { + setTimeout(() => { + handleSaveContact(values); + actions.setSubmitting(false); + }, 400); + }} + > + {({ values, errors, touched, isSubmitting }) => ( +
+ + + {i18n.t("contactModal.form.mainInfo")} + + + +
+ +
+ <> + + setContact({ ...values, disableBot: !values.disableBot }) + } + name="disableBot" + color="primary" + /> + } + /> + + + {i18n.t("contactModal.form.extraInfo")} + + + + {({ push, remove }) => ( + <> + {values.extraInfo && + values.extraInfo.length > 0 && + values.extraInfo.map((info, index) => ( +
+ + + remove(index)} + > + + +
+ ))} +
+ +
+ + )} +
+
+ + + + +
+ )} +
+
+
+ ); +}; + +export default ContactModal; diff --git a/frontend/src/components/ContactNotes/index.js b/frontend/src/components/ContactNotes/index.js new file mode 100644 index 0000000..a7db83c --- /dev/null +++ b/frontend/src/components/ContactNotes/index.js @@ -0,0 +1,204 @@ +import React, { useState, useEffect } from 'react'; +import Button from '@material-ui/core/Button'; +import TextField from '@material-ui/core/TextField'; +import List from '@material-ui/core/List'; +import { makeStyles } from '@material-ui/core/styles'; +import * as Yup from "yup"; +import { Formik, Form, Field } from "formik"; + +import ContactNotesDialogListItem from '../ContactNotesDialogListItem'; +import ConfirmationModal from '../ConfirmationModal'; + +import { toast } from "react-toastify"; + +import { i18n } from "../../translate/i18n"; + +import ButtonWithSpinner from '../ButtonWithSpinner'; + +import useTicketNotes from '../../hooks/useTicketNotes'; +import { Grid } from '@material-ui/core'; + +const useStyles = makeStyles((theme) => ({ + root: { + '& .MuiTextField-root': { + margin: theme.spacing(1), + width: '350px', + }, + }, + list: { + width: '100%', + maxWidth: '350px', + maxHeight: '200px', + backgroundColor: theme.palette.background.paper, + overflow: 'auto' + }, + inline: { + width: '100%' + } +})); + +const NoteSchema = Yup.object().shape({ + note: Yup.string() + .min(2, "Too Short!") + .required("Required") +}); +export function ContactNotes ({ ticket }) { + const { id: ticketId, contactId } = ticket + const classes = useStyles() + const [newNote, setNewNote] = useState({ note: "" }); + const [loading, setLoading] = useState(false) + const [showOnDeleteDialog, setShowOnDeleteDialog] = useState(false) + const [selectedNote, setSelectedNote] = useState({}) + const [notes, setNotes] = useState([]) + const { saveNote, deleteNote, listNotes } = useTicketNotes() + + useEffect(() => { + async function openAndFetchData () { + handleResetState() + await loadNotes() + } + openAndFetchData() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + const handleResetState = () => { + setNewNote({ note: "" }) + setLoading(false) + } + + const handleChangeComment = (e) => { + setNewNote({ note: e.target.value }) + } + + const handleSave = async values => { + setLoading(true) + try { + await saveNote({ + ...values, + ticketId, + contactId + }) + await loadNotes() + setNewNote({ note: '' }) + toast.success('Observação adicionada com sucesso!') + } catch (e) { + toast.error(e) + } + setLoading(false) + } + + const handleOpenDialogDelete = (item) => { + setSelectedNote(item) + setShowOnDeleteDialog(true) + } + + const handleDelete = async () => { + setLoading(true) + try { + await deleteNote(selectedNote.id) + await loadNotes() + setSelectedNote({}) + toast.success('Observação excluída com sucesso!') + } catch (e) { + toast.error(e) + } + setLoading(false) + } + + const loadNotes = async () => { + setLoading(true) + try { + const notes = await listNotes({ ticketId, contactId }) + setNotes(notes) + } catch (e) { + toast.error(e) + } + setLoading(false) + } + + const renderNoteList = () => { + return notes.map((note) => { + return + }) + } + + return ( + <> + + Deseja realmente excluir este registro? + + { + setTimeout(() => { + handleSave(values); + actions.setSubmitting(false); + }, 400); + }} + > + + {({ touched, errors, setErrors }) => ( +
+ + + + + { notes.length > 0 && ( + + + { renderNoteList() } + + + ) } + + + + + + + + Salvar + + + + + +
+ )} +
+ + ); +} \ No newline at end of file diff --git a/frontend/src/components/ContactNotesDialog/index.js b/frontend/src/components/ContactNotesDialog/index.js new file mode 100644 index 0000000..f9debe9 --- /dev/null +++ b/frontend/src/components/ContactNotesDialog/index.js @@ -0,0 +1,204 @@ +import React, { useState, useEffect } from 'react'; +import Button from '@material-ui/core/Button'; +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import TextField from '@material-ui/core/TextField'; +import List from '@material-ui/core/List'; +import { makeStyles } from '@material-ui/core/styles'; +import * as Yup from "yup"; +import { Formik, Form, Field } from "formik"; + +import ContactNotesDialogListItem from '../ContactNotesDialogListItem'; +import ConfirmationModal from '../ConfirmationModal'; + +import { toast } from "react-toastify"; + +import { i18n } from "../../translate/i18n"; + +import ButtonWithSpinner from '../ButtonWithSpinner'; + +import useTicketNotes from '../../hooks/useTicketNotes'; +import { Divider } from '@material-ui/core'; + +const useStyles = makeStyles((theme) => ({ + list: { + backgroundColor: theme.palette.background.paper, + }, +})); + +const NoteSchema = Yup.object().shape({ + note: Yup.string() + .min(2, "Too Short!") + .max(254, "Too long!") + .required("Required") +}); + +export default function ContactNotesDialog ({ modalOpen, onClose, ticket }) { + const { id: ticketId, contactId } = ticket + const classes = useStyles() + const [open, setOpen] = useState(false); + const [newNote, setNewNote] = useState({ note: "" }); + const [loading, setLoading] = useState(false) + const [showOnDeleteDialog, setShowOnDeleteDialog] = useState(false) + const [selectedNote, setSelectedNote] = useState({}) + const [notes, setNotes] = useState([]) + const { saveNote, deleteNote, listNotes } = useTicketNotes() + + useEffect(() => { + async function openAndFetchData () { + if (modalOpen) { + setOpen(true) + handleResetState() + await loadNotes() + } + } + openAndFetchData() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [modalOpen]) + + const handleResetState = () => { + setNewNote({ note: "" }) + setLoading(false) + } + + const handleChangeComment = (e) => { + setNewNote({ note: e.target.value }) + } + + const handleClose = () => { + setOpen(false); + onClose() + }; + + const handleSave = async values => { + setLoading(true) + try { + await saveNote({ + ...values, + ticketId, + contactId + }) + await loadNotes() + setNewNote({ note: '' }) + toast.success('Observação adicionada com sucesso!') + } catch (e) { + toast.error(e) + } + setLoading(false) + } + + const handleOpenDialogDelete = (item) => { + setSelectedNote(item) + setShowOnDeleteDialog(true) + } + + const handleDelete = async () => { + setLoading(true) + try { + await deleteNote(selectedNote.id) + await loadNotes() + setSelectedNote({}) + toast.success('Observação excluída com sucesso!') + } catch (e) { + toast.error(e) + } + setLoading(false) + } + + const loadNotes = async () => { + setLoading(true) + try { + const notes = await listNotes({ ticketId, contactId }) + setNotes(notes) + } catch (e) { + toast.error(e) + } + setLoading(false) + } + + const renderNoteList = () => { + return notes.map((note, index) => { + return ( + <> + + {index < notes.length - 1 && } + + )}) + } + + return ( + <> + + Deseja realmente excluir este registro? + + + + { i18n.t("ticketOptionsMenu.appointmentsModal.title") } + + { + setTimeout(() => { + handleSave(values); + actions.setSubmitting(false); + }, 400); + }} + > + + {({ touched, errors }) => ( +
+ + + + + { renderNoteList() } + + + + + + Salvar + + +
+ )} +
+
+ + ); +} \ No newline at end of file diff --git a/frontend/src/components/ContactNotesDialogListItem/index.js b/frontend/src/components/ContactNotesDialogListItem/index.js new file mode 100644 index 0000000..2b45f71 --- /dev/null +++ b/frontend/src/components/ContactNotesDialogListItem/index.js @@ -0,0 +1,64 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import IconButton from '@material-ui/core/IconButton'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemText from '@material-ui/core/ListItemText'; +import ListItemAvatar from '@material-ui/core/ListItemAvatar'; +import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'; +import Avatar from '@material-ui/core/Avatar'; +import Typography from '@material-ui/core/Typography'; +import { makeStyles } from '@material-ui/core/styles'; +import DeleteIcon from '@material-ui/icons/Delete'; +import moment from 'moment'; + +const useStyles = makeStyles((theme) => ({ + inline: { + width: '100%' + } +})); + +export default function ContactNotesDialogListItem (props) { + const { note, deleteItem } = props; + const classes = useStyles(); + + const handleDelete = (item) => { + deleteItem(item); + } + + return ( + + + + + + + {note.note} + + + } + secondary={ + <> + {note.user.name}, {moment(note.createdAt).format('DD/MM/YY HH:mm')} + + } + /> + + handleDelete(note)} edge="end" aria-label="delete"> + + + + + ) +} + +ContactNotesDialogListItem.propTypes = { + note: PropTypes.object.isRequired, + deleteItem: PropTypes.func.isRequired +} \ No newline at end of file diff --git a/frontend/src/components/ContactTag/index.js b/frontend/src/components/ContactTag/index.js new file mode 100644 index 0000000..b6c838d --- /dev/null +++ b/frontend/src/components/ContactTag/index.js @@ -0,0 +1,26 @@ +import { makeStyles } from "@material-ui/styles"; +import React from "react"; + +const useStyles = makeStyles(theme => ({ + tag: { + padding: "1px 5px", + borderRadius: "3px", + fontSize: "0.8em", + fontWeight: "bold", + color: "#FFF", + marginRight: "5px", + whiteSpace: "nowrap" + } +})); + +const ContactTag = ({ tag }) => { + const classes = useStyles(); + + return ( +
+ {tag.name.toUpperCase()} +
+ ) +} + +export default ContactTag; \ No newline at end of file diff --git a/frontend/src/components/CurrencyInput/index.js b/frontend/src/components/CurrencyInput/index.js new file mode 100644 index 0000000..4cdddc9 --- /dev/null +++ b/frontend/src/components/CurrencyInput/index.js @@ -0,0 +1,50 @@ +import React from 'react' +import PropTypes from 'prop-types' +import MaskedInput from 'react-text-mask' +import createNumberMask from 'text-mask-addons/dist/createNumberMask' + +const defaultMaskOptions = { + prefix: 'R$', + suffix: '', + includeThousandsSeparator: true, + thousandsSeparatorSymbol: '.', + allowDecimal: true, + decimalSymbol: ',', + decimalLimit: 2, // how many digits allowed after the decimal + integerLimit: 7, // limit length of integer numbers + allowNegative: false, + allowLeadingZeroes: false, +} + +const CurrencyInput = ({ maskOptions, ...inputProps }) => { + const currencyMask = createNumberMask({ + ...defaultMaskOptions, + ...maskOptions, + }) + + return +} + +CurrencyInput.defaultProps = { + inputMode: 'numeric', + maskOptions: {}, +} + +CurrencyInput.propTypes = { + inputmode: PropTypes.string, + maskOptions: PropTypes.shape({ + prefix: PropTypes.string, + suffix: PropTypes.string, + includeThousandsSeparator: PropTypes.bool, + thousandsSeparatorSymbol: PropTypes.string, + allowDecimal: PropTypes.bool, + decimalSymbol: PropTypes.string, + decimalLimit: PropTypes.string, + requireDecimal: PropTypes.bool, + allowNegative: PropTypes.bool, + allowLeadingZeroes: PropTypes.bool, + integerLimit: PropTypes.number, + }), +} + +export default CurrencyInput diff --git a/frontend/src/components/DarkMode/index.js b/frontend/src/components/DarkMode/index.js new file mode 100644 index 0000000..014be13 --- /dev/null +++ b/frontend/src/components/DarkMode/index.js @@ -0,0 +1,70 @@ +import React, { useState } from "react"; + +import { makeStyles } from "@material-ui/core/styles"; +import { CssBaseline, IconButton } from "@material-ui/core"; +import Brightness4Icon from "@material-ui/icons/Brightness4"; +import Brightness7Icon from "@material-ui/icons/Brightness7"; + +const useStyles = makeStyles((theme) => ({ + icons: { + color: "#fff", + }, + switch: { + color: "#fff", + }, + visible: { + display: "none", + }, + btnHeader: { + color: "#fff", + }, +})); + +const DarkMode = (props) => { + const classes = useStyles(); + + const [theme, setTheme] = useState("light"); + + const themeToggle = () => { + theme === "light" ? setTheme("dark") : setTheme("light"); + }; + + const handleClick = () => { + props.themeToggle(); + themeToggle(); + }; + + return ( + <> + {theme === "light" ? ( + <> + + + + + + ) : ( + <> + + + + + + )} + + ); +}; + +export default DarkMode; diff --git a/frontend/src/components/Dashboard/CardCounter.js b/frontend/src/components/Dashboard/CardCounter.js new file mode 100644 index 0000000..c8978a6 --- /dev/null +++ b/frontend/src/components/Dashboard/CardCounter.js @@ -0,0 +1,53 @@ +import React from "react"; + +import { Avatar, Card, CardHeader, Typography } from "@material-ui/core"; +import Skeleton from "@material-ui/lab/Skeleton"; + +import { makeStyles } from "@material-ui/core/styles"; +import { grey } from '@material-ui/core/colors'; + +const useStyles = makeStyles(theme => ({ + cardAvatar: { + fontSize: '55px', + color: grey[500], + backgroundColor: '#ffffff', + width: theme.spacing(7), + height: theme.spacing(7) + }, + cardTitle: { + fontSize: '18px', + color: theme.palette.text.primary + }, + cardSubtitle: { + color: grey[600], + fontSize: '14px' + } +})); + +export default function CardCounter(props) { + const { icon, title, value, loading } = props + const classes = useStyles(); + return ( !loading ? + + + {icon} + + } + title={ + + { title } + + } + subheader={ + + { value } + + } + /> + + : + ) + +} \ No newline at end of file diff --git a/frontend/src/components/Dashboard/TableAttendantsStatus.js b/frontend/src/components/Dashboard/TableAttendantsStatus.js new file mode 100644 index 0000000..e60782c --- /dev/null +++ b/frontend/src/components/Dashboard/TableAttendantsStatus.js @@ -0,0 +1,102 @@ +import React from "react"; + +import Paper from "@material-ui/core/Paper"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableContainer from "@material-ui/core/TableContainer"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import Skeleton from "@material-ui/lab/Skeleton"; + +import { makeStyles } from "@material-ui/core/styles"; +import { green, red } from "@material-ui/core/colors"; + +import CheckCircleIcon from "@material-ui/icons/CheckCircle"; +import ErrorIcon from "@material-ui/icons/Error"; +import moment from "moment"; + +import Rating from "@material-ui/lab/Rating"; +import { Tooltip } from "@material-ui/core"; + +const useStyles = makeStyles((theme) => ({ + on: { + color: green[600], + fontSize: "20px", + }, + off: { + color: red[600], + fontSize: "20px", + }, +})); + +export function RatingBox({ rating }) { + const ratingTrunc = rating && rating > 0 ? rating.toFixed(1) : 0; + return ( + +
+ +
+
+ ); +} + +export default function TableAttendantsStatus(props) { + const { loading, attendants } = props; + const classes = useStyles(); + + function renderList() { + return attendants.map((a, k) => ( + + {a.name} + + + + {formatTime(a.avgSupportTime, 2)} + + {a.online ? : } + + + )); + } + + function formatTime(minutes) { + return moment().startOf("day").add(minutes, "minutes").format("HH[h] mm[m]"); + } + + return !loading ? ( + + + + + Nome + Avaliações + T.M. de Atendimento + Status (Atual) + + + + {renderList()} + {/* + Nome 4 + 10 + 10 minutos + + + + + + Nome 5 + 10 + 10 minutos + + + + */} + +
+
+ ) : ( + + ); +} \ No newline at end of file diff --git a/frontend/src/components/DatePickerMoment/index.js b/frontend/src/components/DatePickerMoment/index.js new file mode 100644 index 0000000..1a43043 --- /dev/null +++ b/frontend/src/components/DatePickerMoment/index.js @@ -0,0 +1,59 @@ +import React, { useState } from 'react'; + +import { + KeyboardDatePicker, + MuiPickersUtilsProvider, +} from '@material-ui/pickers'; +import MomentUtils from '@date-io/moment'; +import moment from 'moment'; +import { Box } from '@material-ui/core'; + +export const DatePickerMoment = ({ label, getDate }) => { + const [selectedDate, setDate] = useState(null); + const [inputValue, setInputValue] = useState(null); + + const onDateChange = (date, value) => { + getDate(moment(date).format('YYYY-MM-DD')); + setDate(date); + setInputValue(value); + }; + + const dateFormatter = (str) => { + return str; + }; + + return ( + +
+ + + + +
+
+ ); +}; diff --git a/frontend/src/components/Dialog/index.js b/frontend/src/components/Dialog/index.js new file mode 100644 index 0000000..23bcb28 --- /dev/null +++ b/frontend/src/components/Dialog/index.js @@ -0,0 +1,34 @@ +import React, { useState, useEffect } from 'react'; +import CoreDialog from '@material-ui/core/Dialog'; +import DialogTitle from '@material-ui/core/DialogTitle'; + +function Dialog ({ title, modalOpen, onClose, children }) { + const [open, setOpen] = useState(false); + + useEffect(() => { + setOpen(modalOpen) + }, [modalOpen]) + + const handleClose = () => { + setOpen(false); + onClose() + }; + + return ( + <> + + + {title} + + {children} + + + ); +} + +export default Dialog; \ No newline at end of file diff --git a/frontend/src/components/EditMessageModal/index.js b/frontend/src/components/EditMessageModal/index.js new file mode 100644 index 0000000..075cc80 --- /dev/null +++ b/frontend/src/components/EditMessageModal/index.js @@ -0,0 +1,254 @@ +import React, { useEffect, useState, useRef } from "react"; +import { + Box, + Dialog, + DialogContent, + DialogTitle, + IconButton, + Paper, + InputBase +} from "@material-ui/core"; +import CloseIcon from '@material-ui/icons/Close'; +import CheckCircleIcon from "@material-ui/icons/CheckCircle"; +import whatsBackground from "../../assets/wa-background.png"; +import { makeStyles } from "@material-ui/core"; +import MarkdownWrapper from "../MarkdownWrapper"; +import MoodIcon from "@material-ui/icons/Mood"; +import api from "../../services/api"; +import whatsBackgroundDark from "../../assets/wa-background-dark.png" + +const useStyles = makeStyles((theme) => ({ + messagesList: { + backgroundSize: "370px", + backgroundImage: theme.mode === 'light' ? `url(${whatsBackground})` : `url(${whatsBackgroundDark})`, //DARK MODE PLW DESIGN// + display: "flex", + display: "flex", + justifyContent: "center", + flexGrow: 1, + padding: "20px 20px 20px 20px", + overflowY: "scroll", + "@media (max-width: 600px)": { + paddingBottom: "90px" + }, + ...theme.scrollbarStyles, + minHeight: "150px", + minWidth: "500px" + }, + textContentItem: { + overflowWrap: "break-word", + padding: "3px 80px 6px 6px", + }, + messageRight: { + fontSize: "13px", + marginLeft: 20, + marginTop: 2, + minWidth: 100, + maxWidth: 510, + height: "auto", + display: "block", + position: "relative", + whiteSpace: "pre-wrap", + alignSelf: "flex-end", + borderRadius: 8, + paddingLeft: 5, + paddingRight: 5, + paddingTop: 5, + paddingBottom: 0 + }, + inputmsg:{ + backgroundColor: theme.mode === 'light' ? '#FFF' : '#1c1c1c', + display: "flex", + width: "100%", + margin: "10px 0px 10px 20px", + borderRadius: "10px" + }, + timestamp: { + fontSize: 11, + position: "absolute", + bottom: 0, + right: 5, + color: "#999" + }, + titleBackground: { + color:'#ffff', + backgroundColor: "#00796b" , // Cor de fundo desejada + marginLeft:'3px' + }, + emojiBox: { + position: "absolute", + bottom: 63, + width: 40, + borderTop: "1px solid #e8e8e8", + zIndex:1 + }, +})); + +// const EmojiOptions = React.forwardRef((props, ref) => { +// const { disabled, showEmoji, setShowEmoji, handleAddEmoji } = props; +// const classes = useStyles(); + +// return ( +// <> +// setShowEmoji((prevState) => !prevState)} +// > +// +// + +// {showEmoji ? ( +//
+// +//
+// ) : null} +// +// ); +// }); + +const EditMessageModal = ({ open, onClose, onSave, message }) => { + const classes = useStyles(); + const [editedMessage, setEditedMessage] = useState(null); + const [showEmoji, setShowEmoji] = useState(false); + const [inputMessage, setInputMessage] = useState(""); + const emojiOptionsRef = useRef(null); + const modalRef = useRef(null); + + useEffect(() => { + if (open) { + setEditedMessage(message?.body); + } + }, [open, message]); + + const handleSave = async (editedMessage) => { + if(editedMessage){ + try { + const messages = { + read: 1, + fromMe: true, + mediaUrl: "", + body: editedMessage, + quotedMsg: null, + }; + await api.post(`/messages/edit/${message.id}`,messages) + onClose(false) + } catch (err) { + + } + } + }; + + + const setInputValue = (value) => { + let emoji = value.native; + setEditedMessage(editedMessage ? editedMessage + value.native : emoji); + }; + + useEffect(() => { + if (open) { + // Calculate the position for EmojiOptions inside the modal + if (open && modalRef.current && emojiOptionsRef.current) { + const modalRect = modalRef.current.getBoundingClientRect(); + const emojiOptionsRect = emojiOptionsRef.current.getBoundingClientRect(); + const desiredPosition = { + top: emojiOptionsRect.height > modalRect.height + ? 0 + : modalRect.height - emojiOptionsRect.height, + left: modalRect.width - emojiOptionsRect.width + }; + emojiOptionsRef.current.style.top = `${desiredPosition.top}px`; + emojiOptionsRef.current.style.left = `${desiredPosition.left}px`; + } + }; + }, [open]); + + return ( + onClose(false)} + aria-labelledby="edit-message-dialog" + PaperProps={{ + style: { + zIndex: 1 // Defina um valor alto de zIndex para garantir que o modal sobreponha outros elementos + }, + }} + ref={modalRef} + > + + onClose(false)} aria-label="close"> + + + Editar Mensagem + + + + + + + + {message?.body} + + {/* + {format(parseISO(message?.updatedAt), "HH:mm")} + */} + + + + + + setEditedMessage(e.target.value)} + inputProps={{ "aria-label": "search google maps" }} + /> + {/* */} + + handleSave(editedMessage)}> + + + + + + + ); +}; + +export default EditMessageModal; \ No newline at end of file diff --git a/frontend/src/components/FileModal/index.js b/frontend/src/components/FileModal/index.js new file mode 100644 index 0000000..87b7404 --- /dev/null +++ b/frontend/src/components/FileModal/index.js @@ -0,0 +1,350 @@ +import React, { useState, useEffect, useContext } from "react"; + +import * as Yup from "yup"; +import { + Formik, + Form, + Field, + FieldArray +} from "formik"; +import { toast } from "react-toastify"; + +import { + Box, + Button, + CircularProgress, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Divider, + Grid, + makeStyles, + TextField +} from "@material-ui/core"; +import IconButton from "@material-ui/core/IconButton"; +import Typography from "@material-ui/core/Typography"; +import DeleteOutlineIcon from "@material-ui/icons/DeleteOutline"; +import AttachFileIcon from "@material-ui/icons/AttachFile"; + +import { green } from "@material-ui/core/colors"; + +import { i18n } from "../../translate/i18n"; + +import api from "../../services/api"; +import toastError from "../../errors/toastError"; +import { AuthContext } from "../../context/Auth/AuthContext"; + +const useStyles = makeStyles(theme => ({ + root: { + display: "flex", + flexWrap: "wrap", + gap: 4 + }, + multFieldLine: { + display: "flex", + "& > *:not(:last-child)": { + marginRight: theme.spacing(1), + }, + }, + textField: { + marginRight: theme.spacing(1), + flex: 1, + }, + + extraAttr: { + display: "flex", + justifyContent: "center", + alignItems: "center", + }, + + btnWrapper: { + position: "relative", + }, + + buttonProgress: { + color: green[500], + position: "absolute", + top: "50%", + left: "50%", + marginTop: -12, + marginLeft: -12, + }, + formControl: { + margin: theme.spacing(1), + minWidth: 2000, + }, + colorAdorment: { + width: 20, + height: 20, + }, +})); + +const FileListSchema = Yup.object().shape({ + name: Yup.string() + .min(3, "nome muito curto") + .required("Obrigatório"), + message: Yup.string() + .required("Obrigatório") +}); + +const FilesModal = ({ open, onClose, fileListId, reload }) => { + const classes = useStyles(); + const { user } = useContext(AuthContext); + const [ files, setFiles ] = useState([]); + const [selectedFileNames, setSelectedFileNames] = useState([]); + + + const initialState = { + name: "", + message: "", + options: [{ name: "", path:"", mediaType:"" }], + }; + + const [fileList, setFileList] = useState(initialState); + + useEffect(() => { + try { + (async () => { + if (!fileListId) return; + + const { data } = await api.get(`/files/${fileListId}`); + setFileList(data); + })() + } catch (err) { + toastError(err); + } + }, [fileListId, open]); + + const handleClose = () => { + setFileList(initialState); + setFiles([]); + onClose(); + }; + + const handleSaveFileList = async (values) => { + + const uploadFiles = async (options, filesOptions, id) => { + const formData = new FormData(); + formData.append("fileId", id); + formData.append("typeArch", "fileList") + filesOptions.forEach((fileOption, index) => { + if (fileOption.file) { + formData.append("files", fileOption.file); + formData.append("mediaType", fileOption.file.type) + formData.append("name", options[index].name); + formData.append("id", options[index].id); + } + }); + + try { + const { data } = await api.post(`/files/uploadList/${id}`, formData); + setFiles([]); + return data; + } catch (err) { + toastError(err); + } + return null; + } + + const fileData = { ...values, userId: user.id }; + + try { + if (fileListId) { + const { data } = await api.put(`/files/${fileListId}`, fileData) + if (data.options.length > 0) + + uploadFiles(data.options, values.options, fileListId) + } else { + const { data } = await api.post("/files", fileData); + if (data.options.length > 0) + uploadFiles(data.options, values.options, data.id) + } + toast.success(i18n.t("fileModal.success")); + if (typeof reload == 'function') { + reload(); + } + } catch (err) { + toastError(err); + } + handleClose(); + }; + + return ( +
+ + + {(fileListId ? `${i18n.t("fileModal.title.edit")}` : `${i18n.t("fileModal.title.add")}`)} + + { + setTimeout(() => { + handleSaveFileList(values); + actions.setSubmitting(false); + }, 400); + }} + > + {({ touched, errors, isSubmitting, values }) => ( +
+ +
+ +
+
+
+ +
+ + {i18n.t("fileModal.form.fileOptions")} + + + + {({ push, remove }) => ( + <> + {values.options && + values.options.length > 0 && + values.options.map((info, index) => ( +
+ + + + + + { + const selectedFile = e.target.files[0]; + const updatedOptions = [...values.options]; + updatedOptions[index].file = selectedFile; + + setFiles('options', updatedOptions); + + // Atualize a lista selectedFileNames para o campo específico + const updatedFileNames = [...selectedFileNames]; + updatedFileNames[index] = selectedFile ? selectedFile.name : ''; + setSelectedFileNames(updatedFileNames); + }} + style={{ display: 'none' }} + name={`options[${index}].file`} + id={`file-upload-${index}`} + /> + + remove(index)} + > + + + + + {info.path? info.path : selectedFileNames[index]} + + +
+ + ))} +
+ +
+ + )} +
+
+ + + + +
+ )} +
+
+
+ ); +}; + +export default FilesModal; \ No newline at end of file diff --git a/frontend/src/components/FormFields/CheckboxField.js b/frontend/src/components/FormFields/CheckboxField.js new file mode 100644 index 0000000..c7688ff --- /dev/null +++ b/frontend/src/components/FormFields/CheckboxField.js @@ -0,0 +1,38 @@ +import React from 'react'; +import { at } from 'lodash'; +import { useField } from 'formik'; +import { + Checkbox, + FormControl, + FormControlLabel, + FormHelperText +} from '@material-ui/core'; + +export default function CheckboxField(props) { + const { label, ...rest } = props; + const [field, meta, helper] = useField(props); + const { setValue } = helper; + + function _renderHelperText() { + const [touched, error] = at(meta, 'touched', 'error'); + if (touched && error) { + return {error}; + } + } + + function _onChange(e) { + setValue(e.target.checked); + } + + return ( + + } + label={label} + /> + {_renderHelperText()} + + ); +} diff --git a/frontend/src/components/FormFields/DatePickerField.js b/frontend/src/components/FormFields/DatePickerField.js new file mode 100644 index 0000000..503396e --- /dev/null +++ b/frontend/src/components/FormFields/DatePickerField.js @@ -0,0 +1,54 @@ +import React, { useState, useEffect } from 'react'; +import { useField } from 'formik'; +import Grid from '@material-ui/core/Grid'; +import { + MuiPickersUtilsProvider, + KeyboardDatePicker +} from '@material-ui/pickers'; +import DateFnsUtils from '@date-io/date-fns'; + +export default function DatePickerField(props) { + const [field, meta, helper] = useField(props); + const { touched, error } = meta; + const { setValue } = helper; + const isError = touched && error && true; + const { value } = field; + const [selectedDate, setSelectedDate] = useState(null); + + useEffect(() => { + if (value) { + const date = new Date(value); + setSelectedDate(date); + } + }, [value]); + + function _onChange(date) { + if (date) { + setSelectedDate(date); + try { + const ISODateString = date.toISOString(); + setValue(ISODateString); + } catch (error) { + setValue(date); + } + } else { + setValue(date); + } + } + + return ( + + + + + + ); +} diff --git a/frontend/src/components/FormFields/InputField.js b/frontend/src/components/FormFields/InputField.js new file mode 100644 index 0000000..ecc68b2 --- /dev/null +++ b/frontend/src/components/FormFields/InputField.js @@ -0,0 +1,26 @@ +import React from 'react'; +import { at } from 'lodash'; +import { useField } from 'formik'; +import { TextField } from '@material-ui/core'; + +export default function InputField(props) { + const { errorText, ...rest } = props; + const [field, meta] = useField(props); + + function _renderHelperText() { + const [touched, error] = at(meta, 'touched', 'error'); + if (touched && error) { + return error; + } + } + + return ( + + ); +} diff --git a/frontend/src/components/FormFields/SelectField.js b/frontend/src/components/FormFields/SelectField.js new file mode 100644 index 0000000..35ca7e2 --- /dev/null +++ b/frontend/src/components/FormFields/SelectField.js @@ -0,0 +1,48 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { at } from 'lodash'; +import { useField } from 'formik'; +import { + InputLabel, + FormControl, + Select, + MenuItem, + FormHelperText +} from '@material-ui/core'; + +function SelectField(props) { + const { label, data, ...rest } = props; + const [field, meta] = useField(props); + const { value: selectedValue } = field; + const [touched, error] = at(meta, 'touched', 'error'); + const isError = touched && error && true; + function _renderHelperText() { + if (isError) { + return {error}; + } + } + + return ( + + {label} + + {_renderHelperText()} + + ); +} + +SelectField.defaultProps = { + data: [] +}; + +SelectField.propTypes = { + data: PropTypes.array.isRequired +}; + +export default SelectField; diff --git a/frontend/src/components/FormFields/index.js b/frontend/src/components/FormFields/index.js new file mode 100644 index 0000000..9fa1775 --- /dev/null +++ b/frontend/src/components/FormFields/index.js @@ -0,0 +1,5 @@ +import InputField from './InputField'; +import CheckboxField from './CheckboxField'; +import SelectField from './SelectField'; +import DatePickerField from './DatePickerField'; +export { InputField, CheckboxField, SelectField, DatePickerField }; diff --git a/frontend/src/components/ForwardMessageModal/index.js b/frontend/src/components/ForwardMessageModal/index.js new file mode 100644 index 0000000..26717d6 --- /dev/null +++ b/frontend/src/components/ForwardMessageModal/index.js @@ -0,0 +1,229 @@ +import React, { useState, useEffect, useContext } from "react"; +import { useHistory } from "react-router-dom"; + +import TextField from "@material-ui/core/TextField"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import Autocomplete, { + createFilterOptions, +} from "@material-ui/lab/Autocomplete"; +import CircularProgress from "@material-ui/core/CircularProgress"; + +import { i18n } from "../../translate/i18n"; +import api from "../../services/api"; +import ButtonWithSpinner from "../ButtonWithSpinner"; +import ContactModal from "../ContactModal"; +import toastError from "../../errors/toastError"; +import { AuthContext } from "../../context/Auth/AuthContext"; + +import { FormControlLabel, Switch, Typography } from "@material-ui/core"; + +const ForwardMessageModal = ({ messages, onClose, modalOpen }) => { + const [optionsContacts, setOptionsContacts] = useState([]); + const [loading, setLoading] = useState(false); + const [searchParam, setSearchParam] = useState(""); + const [selectedContact, setSelectedContact] = useState(null); + const [newContact, setNewContact] = useState({}); + const [contactModalOpen, setContactModalOpen] = useState(false); + const { user } = useContext(AuthContext); + const [sending, setSending] = useState(false); + const [messageSending, setMessageSending] = useState(''); + const [signMessage, setSignMessage] = useState(true); + + useEffect(() => { + if (!modalOpen || searchParam.length < 3) { + setLoading(false); + return; + } + setLoading(true); + const delayDebounceFn = setTimeout(() => { + const fetchContacts = async () => { + try { + const { data } = await api.get("contacts", { + params: { searchParam }, + }); + setOptionsContacts(data.contacts); + setLoading(false); + } catch (err) { + setLoading(false); + toastError(err); + } + }; + + fetchContacts(); + }, 500); + return () => clearTimeout(delayDebounceFn); + }, [searchParam, modalOpen]); + + const history = useHistory(); + + const sleep = (ms) => { + return new Promise(resolve => setTimeout(resolve, ms)); + }; + + const handleForwardMessage = async (contactL) => { + const responseList = []; + for (const message of messages) { + setSending(true); + try { + setMessageSending(message.id); + const response = await api.post('/message/forward', { messageId: message.id, contactId: contactL.id, signMessage: signMessage }); + responseList.push(response); + sleep(900); + } catch (error) { + toastError(error); + } + } + setSending(false); + handleClose(); + // history.push('/tickets'); + } + + const handleSelectOption = (e, newValue) => { + if (newValue?.number) { + setSelectedContact(newValue); + } else if (newValue?.name) { + setNewContact({ name: newValue.name }); + setContactModalOpen(true); + } + }; + + const handleClose = () => { + onClose(); + setSearchParam(""); + setSelectedContact(null); + setSending(false); + }; + + const handleCloseContactModal = () => { + setContactModalOpen(false); + }; + + const renderOption = optionL => { + if (optionL.number) { + return `${optionL.name} - ${optionL.number}`; + } else { + return `Nenhum contato encontrado com o nome ${optionL.name}`; + } + }; + + const renderOptionLabel = optionL => { + if (optionL.number) { + return `${optionL.name} - ${optionL.number}`; + } else { + return `${optionL.name}`; + } + }; + + const filter = createFilterOptions({ + trim: true, + }); + + const createAddContactOption = (filterOptions, params) => { + const filtered = filter(filterOptions, params); + + if (params.inputValue !== "" && !loading && searchParam.length >= 3) { + filtered.push({ + name: `${params.inputValue}`, + }); + } + + return filtered; + }; + + return ( + <> + + + + Encaminhar mensagem + + + handleSelectOption(e, newValue)} + renderInput={params => ( + setSearchParam(e.target.value)} + onKeyPress={e => { + if (loading || !selectedContact) return; + else if (e.key === "Enter") { + // handleSaveTicket(selectedContact.id); + } + }} + InputProps={{ + ...params.InputProps, + endAdornment: ( + + {loading ? ( + + ) : null} + {params.InputProps.endAdornment} + + ), + }} + /> + )} + /> + + + {sending && ( + <> + + + Enviando {messageSending}... + + + )} + { + setSignMessage(e.target.checked); + }} + name="showAllTickets" + color="primary" + /> + } + /> + handleForwardMessage(selectedContact)} + color="primary" + loading={loading} + > + Encaminhar + + + + + ); +}; + +export default ForwardMessageModal; \ No newline at end of file diff --git a/frontend/src/components/HelpsManager/index.js b/frontend/src/components/HelpsManager/index.js new file mode 100644 index 0000000..5e7c2ac --- /dev/null +++ b/frontend/src/components/HelpsManager/index.js @@ -0,0 +1,290 @@ +import React, { useState, useEffect } from "react"; +import { + makeStyles, + Paper, + Grid, + TextField, + Table, + TableHead, + TableBody, + TableCell, + TableRow, + IconButton +} from "@material-ui/core"; +import { Formik, Form, Field } from 'formik'; +import ButtonWithSpinner from "../ButtonWithSpinner"; +import ConfirmationModal from "../ConfirmationModal"; + +import { Edit as EditIcon } from "@material-ui/icons"; + +import { toast } from "react-toastify"; +import useHelps from "../../hooks/useHelps"; + + +const useStyles = makeStyles(theme => ({ + root: { + width: '100%' + }, + mainPaper: { + width: '100%', + flex: 1, + padding: theme.spacing(2) + }, + fullWidth: { + width: '100%' + }, + tableContainer: { + width: '100%', + overflowX: "scroll", + ...theme.scrollbarStyles + }, + textfield: { + width: '100%' + }, + textRight: { + textAlign: 'right' + }, + row: { + paddingTop: theme.spacing(2), + paddingBottom: theme.spacing(2) + }, + control: { + paddingRight: theme.spacing(1), + paddingLeft: theme.spacing(1) + }, + buttonContainer: { + textAlign: 'right', + padding: theme.spacing(1) + } +})); + +export function HelpManagerForm (props) { + const { onSubmit, onDelete, onCancel, initialValue, loading } = props; + const classes = useStyles() + + const [record, setRecord] = useState(initialValue); + + useEffect(() => { + setRecord(initialValue) + }, [initialValue]) + + const handleSubmit = async(data) => { + onSubmit(data) + } + + return ( + + setTimeout(() => { + handleSubmit(values) + resetForm() + }, 500) + } + > + {(values) => ( +
+ + + + + + + + + + + + onCancel()} variant="contained"> + Limpar + + + { record.id !== undefined ? ( + + onDelete(record)} variant="contained" color="secondary"> + Excluir + + + ) : null} + + + Salvar + + + +
+ )} +
+ ) +} + +export function HelpsManagerGrid (props) { + const { records, onSelect } = props + const classes = useStyles() + + return ( + + + + + # + Título + Descrição + Vídeo + + + + {records.map((row) => ( + + + onSelect(row)} aria-label="delete"> + + + + {row.title || '-'} + {row.description || '-'} + {row.video || '-'} + + ))} + +
+
+ ) +} + +export default function HelpsManager () { + const classes = useStyles() + const { list, save, update, remove } = useHelps() + + const [showConfirmDialog, setShowConfirmDialog] = useState(false) + const [loading, setLoading] = useState(false) + const [records, setRecords] = useState([]) + const [record, setRecord] = useState({ + title: '', + description: '', + video: '' + }) + + useEffect(() => { + async function fetchData () { + await loadHelps() + } + fetchData() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + const loadHelps = async () => { + setLoading(true) + try { + const helpList = await list() + setRecords(helpList) + } catch (e) { + toast.error('Não foi possível carregar a lista de registros') + } + setLoading(false) + } + + const handleSubmit = async (data) => { + setLoading(true) + try { + if (data.id !== undefined) { + await update(data) + } else { + await save(data) + } + await loadHelps() + handleCancel() + toast.success('Operação realizada com sucesso!') + } catch (e) { + toast.error('Não foi possível realizar a operação. Verifique se já existe uma helpo com o mesmo nome ou se os campos foram preenchidos corretamente') + } + setLoading(false) + } + + const handleDelete = async () => { + setLoading(true) + try { + await remove(record.id) + await loadHelps() + handleCancel() + toast.success('Operação realizada com sucesso!') + } catch (e) { + toast.error('Não foi possível realizar a operação') + } + setLoading(false) + } + + const handleOpenDeleteDialog = () => { + setShowConfirmDialog(true) + } + + const handleCancel = () => { + setRecord({ + title: '', + description: '', + video: '' + }) + } + + const handleSelect = (data) => { + setRecord({ + id: data.id, + title: data.title || '', + description: data.description || '', + video: data.video || '' + }) + } + + return ( + + + + + + + + + + setShowConfirmDialog(false)} + onConfirm={() => handleDelete()} + > + Deseja realmente excluir esse registro? + + + ) +} \ No newline at end of file diff --git a/frontend/src/components/HubNotificaMeDialog/index.js b/frontend/src/components/HubNotificaMeDialog/index.js new file mode 100644 index 0000000..ab0b284 --- /dev/null +++ b/frontend/src/components/HubNotificaMeDialog/index.js @@ -0,0 +1,200 @@ +import React, { useContext, useState, useEffect, useRef } from "react"; + +import * as Yup from "yup"; +import { Formik, Form, Field } from "formik"; +import { toast } from "react-toastify"; + +import { makeStyles } from "@material-ui/core/styles"; +import { green } from "@material-ui/core/colors"; +import Button from "@material-ui/core/Button"; +import TextField from "@material-ui/core/TextField"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import AttachFileIcon from "@material-ui/icons/AttachFile"; +import DeleteOutlineIcon from "@material-ui/icons/DeleteOutline"; +import IconButton from "@material-ui/core/IconButton"; +import MenuItem from "@material-ui/core/MenuItem"; +import { i18n } from "../../translate/i18n"; +import { head } from "lodash"; +import api from "../../services/api"; +import toastError from "../../errors/toastError"; +import { AuthContext } from "../../context/Auth/AuthContext"; +import MessageVariablesPicker from "../MessageVariablesPicker"; +import ButtonWithSpinner from "../ButtonWithSpinner"; + +const useStyles = makeStyles((theme) => ({ + root: { + display: "flex", + flexWrap: "wrap", + }, + multFieldLine: { + display: "flex", + "& > *:not(:last-child)": { + marginRight: theme.spacing(1), + }, + }, + + btnWrapper: { + position: "relative", + }, + + buttonProgress: { + color: green[500], + position: "absolute", + top: "50%", + left: "50%", + marginTop: -12, + marginLeft: -12, + }, + formControl: { + margin: theme.spacing(1), + minWidth: 120, + }, + colorAdorment: { + width: 20, + height: 20, + }, +})); + +const HubNotificaMeSchema = Yup.object().shape({ + token: Yup.string().required("Obrigatório"), + tipo: Yup.string().oneOf(["Facebook", "Instagram"], "Tipo inválido").required("Obrigatório"), +}); + +const HubNotificaMeDialog = ({ open, onClose, hubnotificameId, reload }) => { + + const classes = useStyles(); + const { user } = useContext(AuthContext); + const { profile } = user; + + + const initialState = { + nome: "", + token: "", + tipo: "", + }; + + const [hubnotificame, setHubNotificaMe] = useState(initialState); + + + useEffect(() => { + try { + (async () => { + if (!hubnotificameId) return; + + const { data } = await api.get(`/hub-notificame/${hubnotificameId}`); + setHubNotificaMe({ nome: data.nome, token: data.token, tipo: data.tipo }); + })(); + } catch (err) { + toastError(err); + } + }, [hubnotificameId, open]); + + const handleClose = () => { + setHubNotificaMe(initialState); + onClose(); + }; + + const handleSaveHubNotificaMe = async (values) => { + + try { + await api.post("/hub-notificame", values); + toast.success("Registro criado com sucesso!"); + handleClose(); + } catch (err) { + toastError(err); + } + + + }; + + return ( + + Adicionar Token + + {({ values, touched, errors, isSubmitting }) => { + console.log("Valores do formulário em tempo real:", values); // Debug + + return ( +
+ + + {/* Campo Nome */} + + + {/* Campo Token */} + + + {/* Select para escolher o tipo */} + + Facebook + Instagram + + + + + + +
+ ); + }} +
+
+ ); +}; + +export default HubNotificaMeDialog; \ No newline at end of file diff --git a/frontend/src/components/Kanban/CardTitle/index.js b/frontend/src/components/Kanban/CardTitle/index.js new file mode 100644 index 0000000..3123dd8 --- /dev/null +++ b/frontend/src/components/Kanban/CardTitle/index.js @@ -0,0 +1,60 @@ +import { Avatar, makeStyles } from '@material-ui/core'; +import React from 'react'; + +const useStyles = makeStyles(theme => ({ + container: { + position: "relative", + display: "flex", + gap: "8px", + alignItems: "center", + width: "100%" + }, + titleAndSubtitleContainer: { + maxWidth: "150px", + display: "flex", + flexShrink: 1, + flexDirection: "column", + }, + subtitle: { + fontSize: "12px", + fontWeight: "normal", + color: "#4d4d4d", + textOverflow: "ellipsis", + whiteSpace: "nowrap", + overflow: "hidden" + }, + title: { + textOverflow: "ellipsis", + whiteSpace: "nowrap", + overflow: "hidden" + }, + deleteButton: { + position: "absolute", + right: "0px" + } + })); + +const CardTitle = ({ticket, userProfile}) => { + const classes = useStyles(); + + return ( +
+ +
+
+ + {ticket.contact.name} + + + {ticket.contact.number} + +
+
+
+ ) +} + +export default CardTitle; \ No newline at end of file diff --git a/frontend/src/components/Kanban/DeleteButton/index.js b/frontend/src/components/Kanban/DeleteButton/index.js new file mode 100644 index 0000000..3223a6a --- /dev/null +++ b/frontend/src/components/Kanban/DeleteButton/index.js @@ -0,0 +1,58 @@ +import React from 'react'; +import { IconButton, Tooltip } from "@material-ui/core"; +import { Can } from "../../Can"; +import { Trash } from "react-feather"; +import { i18n } from "../../../translate/i18n"; +import ConfirmationModal from "../../ConfirmationModal"; +import { useState } from "react"; +import api from "../../../services/api"; +import toastError from '../../../errors/toastError'; +import { toast } from "react-toastify"; + +export default function DeleteButton({userProfile, ticket, setTickets}) { + + const [confirmationOpen, setConfirmationOpen] = useState(false); + + const handleOpenConfirmationModal = e => { + setConfirmationOpen(true); + // handleClose(); + }; + + const handleDeleteTicket = async () => { + try { + await api.delete(`/tickets/${ticket.id}`); + setTickets(prevTickets => prevTickets.filter(item => item.id !== ticket.id )) + toast.success("Ticket excluído com sucesso") + } catch (err) { + toastError(err); + } + }; + + return ( + <> + ( + + + + + + )} + /> + + {i18n.t("ticketOptionsMenu.confirmationModal.message")} + + + ) +} \ No newline at end of file diff --git a/frontend/src/components/Kanban/FooterButtons/index.js b/frontend/src/components/Kanban/FooterButtons/index.js new file mode 100644 index 0000000..627f455 --- /dev/null +++ b/frontend/src/components/Kanban/FooterButtons/index.js @@ -0,0 +1,72 @@ +import { IconButton, makeStyles, Tooltip } from "@material-ui/core"; +import React, { useState } from "react"; +import { BookOpen, Calendar } from "react-feather"; +import WhatsAppIcon from "@material-ui/icons/WhatsApp"; +import ScheduleModal from "../../ScheduleModal"; +import { useHistory } from "react-router-dom/cjs/react-router-dom.min"; +import ContactNotesDialog from "../../ContactNotesDialog"; + +const useStyles = makeStyles(theme => ({ + container: { + display: "flex", + alignItems: "center" + } + })); + +export default function FooterButtons({ticket}) { + const classes = useStyles(); + const color = "#4d4d4d" + const [scheduleModalOpen, setScheduleModalOpen] = useState(false); + const [contactNotesModal, setContactNotesModal] = useState(false) + const history = useHistory(); + + const handleOpenScheduleModal = () => { + setScheduleModalOpen(true); + }; + + const handleOpenContactNotesModal = () => { + setContactNotesModal(true) + } + + const handleCloseContactNotesModal = () => { + setContactNotesModal(false) + } + + const handleCloseScheduleModal = () => { + setScheduleModalOpen(false); + }; + + const handleSelectTicket = () => { + history.push(`/tickets/${ticket.uuid}`); + }; + + return ( + <> + +
+ + + + + + + + + + + + + + + + + +
+ + ) +} \ No newline at end of file diff --git a/frontend/src/components/Kanban/LaneTitle/index.js b/frontend/src/components/Kanban/LaneTitle/index.js new file mode 100644 index 0000000..035affd --- /dev/null +++ b/frontend/src/components/Kanban/LaneTitle/index.js @@ -0,0 +1,37 @@ +import React from 'react'; +import { makeStyles } from "@material-ui/core"; + +const useStyles = makeStyles(theme => ({ + kanbanSquare: { + width: "1.2rem", + height: "1.2rem", + borderRadius: "5px" + }, + container: { + display: "flex", + gap: "5px", + alignItems: "center" + }, + quantity: { + fontSize: ".75rem", + fontWeight: "normal", + color: "#000000DE", + backgroundColor: "#d9d9d9", + padding: "0 8px", + borderRadius: "5px" + } +})); + +const LaneTitle = ({squareColor, firstLane, children, quantity}) => { + const classes = useStyles(); + + return ( +
+ {!firstLane ?
:
} + {children} +
{quantity}
+
+ ) +} + +export default LaneTitle; \ No newline at end of file diff --git a/frontend/src/components/LocationPreview/index.js b/frontend/src/components/LocationPreview/index.js new file mode 100644 index 0000000..c7f7b5e --- /dev/null +++ b/frontend/src/components/LocationPreview/index.js @@ -0,0 +1,50 @@ +import React, { useEffect } from 'react'; +import toastError from "../../errors/toastError"; + +import { Button, Divider, Typography} from "@material-ui/core"; + +const LocationPreview = ({ image, link, description }) => { + useEffect(() => {}, [image, link, description]); + + const handleLocation = async() => { + try { + window.open(link); + } catch (err) { + toastError(err); + } + } + + return ( + <> +
+
+
+ loc +
+ { description && ( +
+ +
') }}>
+
+
+ )} +
+
+ + +
+
+
+ + ); + +}; + +export default LocationPreview; \ No newline at end of file diff --git a/frontend/src/components/MainContainer/index.js b/frontend/src/components/MainContainer/index.js new file mode 100644 index 0000000..24b7b9a --- /dev/null +++ b/frontend/src/components/MainContainer/index.js @@ -0,0 +1,31 @@ +import React from "react"; + +import { makeStyles } from "@material-ui/core/styles"; +import Container from "@material-ui/core/Container"; + +const useStyles = makeStyles(theme => ({ + mainContainer: { + flex: 1, + padding: theme.spacing(2), + height: `calc(100% - 48px)`, + }, + + contentWrapper: { + height: "100%", + overflowY: "hidden", + display: "flex", + flexDirection: "column", + }, +})); + +const MainContainer = ({ children }) => { + const classes = useStyles(); + + return ( + +
{children}
+
+ ); +}; + +export default MainContainer; diff --git a/frontend/src/components/MainHeader/index.js b/frontend/src/components/MainHeader/index.js new file mode 100644 index 0000000..46fa8ab --- /dev/null +++ b/frontend/src/components/MainHeader/index.js @@ -0,0 +1,19 @@ +import React from "react"; + +import { makeStyles } from "@material-ui/core/styles"; + +const useStyles = makeStyles(theme => ({ + contactsHeader: { + display: "flex", + alignItems: "center", + padding: "0px 6px 6px 6px", + }, +})); + +const MainHeader = ({ children }) => { + const classes = useStyles(); + + return
{children}
; +}; + +export default MainHeader; diff --git a/frontend/src/components/MainHeaderButtonsWrapper/index.js b/frontend/src/components/MainHeaderButtonsWrapper/index.js new file mode 100644 index 0000000..ed5887c --- /dev/null +++ b/frontend/src/components/MainHeaderButtonsWrapper/index.js @@ -0,0 +1,21 @@ +import React from "react"; + +import { makeStyles } from "@material-ui/core/styles"; + +const useStyles = makeStyles(theme => ({ + MainHeaderButtonsWrapper: { + flex: "none", + marginLeft: "auto", + "& > *": { + margin: theme.spacing(1), + }, + }, +})); + +const MainHeaderButtonsWrapper = ({ children }) => { + const classes = useStyles(); + + return
{children}
; +}; + +export default MainHeaderButtonsWrapper; diff --git a/frontend/src/components/MarkdownWrapper/index.js b/frontend/src/components/MarkdownWrapper/index.js new file mode 100644 index 0000000..b827163 --- /dev/null +++ b/frontend/src/components/MarkdownWrapper/index.js @@ -0,0 +1,229 @@ +import Avatar from "@material-ui/core/Avatar"; +import Markdown from "markdown-to-jsx"; +import React from "react"; + +const elements = [ + "a", + "abbr", + "address", + "area", + "article", + "aside", + "audio", + "b", + "base", + "bdi", + "bdo", + "big", + "blockquote", + "body", + "br", + "button", + "canvas", + "caption", + "cite", + "code", + "col", + "colgroup", + "data", + "datalist", + "dd", + "del", + "details", + "dfn", + "dialog", + "div", + "dl", + "dt", + "em", + "embed", + "fieldset", + "figcaption", + "figure", + "footer", + "form", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "head", + "header", + "hgroup", + "hr", + "html", + "i", + "iframe", + "img", + "input", + "ins", + "kbd", + "keygen", + "label", + "legend", + "li", + "link", + "main", + "map", + "mark", + "marquee", + "menu", + "menuitem", + "meta", + "meter", + "nav", + "noscript", + "object", + "ol", + "optgroup", + "option", + "output", + "p", + "param", + "picture", + "pre", + "progress", + "q", + "rp", + "rt", + "ruby", + "s", + "samp", + "script", + "section", + "select", + "small", + "source", + "span", + "strong", + "style", + "sub", + "summary", + "sup", + "table", + "tbody", + "td", + "textarea", + "tfoot", + "th", + "thead", + "time", + "title", + "tr", + "track", + "u", + "ul", + "var", + "video", + "wbr", + + // SVG + "circle", + "clipPath", + "defs", + "ellipse", + "foreignObject", + "g", + "image", + "line", + "linearGradient", + "marker", + "mask", + "path", + "pattern", + "polygon", + "polyline", + "radialGradient", + "rect", + "stop", + "svg", + "text", + "tspan", +]; + +const allowedElements = ["a", "b", "strong", "em", "u", "code", "del"]; + +const CustomLink = ({ children, ...props }) => ( + + {children} + +); + +const MarkdownWrapper = ({ children, message }) => { + let type = message?.mediaType; + console.log('type', type) + const boldRegex = /\*(.*?)\*/g; + const tildaRegex = /~(.*?)~/g; + + if (children && boldRegex.test(children)) { + children = children.replace(boldRegex, "**$1**"); + } + if (children && tildaRegex.test(children)) { + children = children.replace(tildaRegex, "~~$1~~"); + } + + const options = React.useMemo(() => { + const markdownOptions = { + disableParsingRawHTML: true, + forceInline: true, + overrides: { + a: { component: CustomLink }, + }, + }; + + elements.forEach(element => { + if (!allowedElements.includes(element)) { + markdownOptions.overrides[element] = el => el.children || null; + } + }); + + return markdownOptions; + }, []); + + if (!children) return null; + const regex = /(?<=FN:)(.*)(?=\n)|(?<=TEL;.*:)(.*)(?=\n)/g; + + // Executar a expressão regular na string do vCard + const matches = children.match(regex); + + // Extrair o nome e o número de telefone + const contact = matches ? matches[0] : ''; + const number = matches ? matches[1] : ''; + const vcardStyle = { + backgroundColor: 'rgb(74 222 128)', + border: '1.5px solid green', + borderRadius: '4px', + width: '300px', + display: 'flex', + alignItems: 'center', + padding: '5px 0', + }; + + const avatar = { + marginLeft: '10px', + }; + + const infoStyle = { + marginLeft: '10px', + }; + const p = { + margin: '2px', + } + + + if (type === 'contactMessage') { + return ( +
+ +
+

Nome: {contact}

+

Número: {number}

+
+
+ ) + } + return {children}; +}; + +export default MarkdownWrapper; diff --git a/frontend/src/components/MessageInput/RecordingTimer.js b/frontend/src/components/MessageInput/RecordingTimer.js new file mode 100644 index 0000000..108cf50 --- /dev/null +++ b/frontend/src/components/MessageInput/RecordingTimer.js @@ -0,0 +1,48 @@ +import React, { useState, useEffect } from "react"; +import { makeStyles } from "@material-ui/core/styles"; + +const useStyles = makeStyles(theme => ({ + timerBox: { + display: "flex", + marginLeft: 10, + marginRight: 10, + alignItems: "center", + }, +})); + +const RecordingTimer = () => { + const classes = useStyles(); + const initialState = { + minutes: 0, + seconds: 0, + }; + const [timer, setTimer] = useState(initialState); + + useEffect(() => { + const interval = setInterval( + () => + setTimer(prevState => { + if (prevState.seconds === 59) { + return { ...prevState, minutes: prevState.minutes + 1, seconds: 0 }; + } + return { ...prevState, seconds: prevState.seconds + 1 }; + }), + 1000 + ); + return () => { + clearInterval(interval); + }; + }, []); + + const addZero = n => { + return n < 10 ? "0" + n : n; + }; + + return ( +
+ {`${addZero(timer.minutes)}:${addZero(timer.seconds)}`} +
+ ); +}; + +export default RecordingTimer; diff --git a/frontend/src/components/MessageInput/index.js b/frontend/src/components/MessageInput/index.js new file mode 100644 index 0000000..a097e9b --- /dev/null +++ b/frontend/src/components/MessageInput/index.js @@ -0,0 +1,534 @@ +import React, { useState, useEffect, useContext, useRef } from "react"; +import "emoji-mart/css/emoji-mart.css"; +import { useParams } from "react-router-dom"; +import { Picker } from "emoji-mart"; +import MicRecorder from "mic-recorder-to-mp3"; +import clsx from "clsx"; + +import { makeStyles } from "@material-ui/core/styles"; +import Paper from "@material-ui/core/Paper"; +import InputBase from "@material-ui/core/InputBase"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import { green } from "@material-ui/core/colors"; +import AttachFileIcon from "@material-ui/icons/AttachFile"; +import IconButton from "@material-ui/core/IconButton"; +import MoodIcon from "@material-ui/icons/Mood"; +import SendIcon from "@material-ui/icons/Send"; +import CancelIcon from "@material-ui/icons/Cancel"; +import ClearIcon from "@material-ui/icons/Clear"; +import MicIcon from "@material-ui/icons/Mic"; +import CheckCircleOutlineIcon from "@material-ui/icons/CheckCircleOutline"; +import HighlightOffIcon from "@material-ui/icons/HighlightOff"; +import { FormControlLabel, Switch } from "@material-ui/core"; + +import { i18n } from "../../translate/i18n"; +import api from "../../services/api"; +import RecordingTimer from "./RecordingTimer"; +import { ReplyMessageContext } from "../../context/ReplyingMessage/ReplyingMessageContext"; +import { AuthContext } from "../../context/Auth/AuthContext"; +import { useLocalStorage } from "../../hooks/useLocalStorage"; +import { ForwardMessageContext } from "../../context/ForwarMessage/ForwardMessageContext"; +import toastError from "../../errors/toastError"; + +const Mp3Recorder = new MicRecorder({ bitRate: 128 }); + +const useStyles = makeStyles(theme => ({ + mainWrapper: { + backgroundColor: theme.palette.bordabox, //DARK MODE PLW DESIGN// + display: "flex", + flexDirection: "column", + alignItems: "center", + borderTop: "1px solid rgba(0, 0, 0, 0.12)", + }, + + newMessageBox: { + background: "#eee", + width: "100%", + display: "flex", + padding: "7px", + alignItems: "center", + }, + + messageInputWrapper: { + padding: 6, + marginRight: 7, + background: "#fff", + display: "flex", + borderRadius: 20, + flex: 1, + }, + + messageInput: { + paddingLeft: 10, + flex: 1, + border: "none", + }, + + sendMessageIcons: { + color: "grey", + }, + + uploadInput: { + display: "none", + }, + + viewMediaInputWrapper: { + display: "flex", + padding: "10px 13px", + position: "relative", + justifyContent: "space-between", + alignItems: "center", + backgroundColor: "#eee", + borderTop: "1px solid rgba(0, 0, 0, 0.12)", + }, + + emojiBox: { + position: "absolute", + bottom: 63, + width: 40, + borderTop: "1px solid #e8e8e8", + }, + + circleLoading: { + color: green[500], + opacity: "70%", + position: "absolute", + top: "20%", + left: "50%", + marginLeft: -12, + }, + + audioLoading: { + color: green[500], + opacity: "70%", + }, + + recorderWrapper: { + display: "flex", + alignItems: "center", + alignContent: "middle", + }, + + cancelAudioIcon: { + color: "red", + }, + + sendAudioIcon: { + color: "green", + }, + + replyginMsgWrapper: { + display: "flex", + width: "100%", + alignItems: "center", + justifyContent: "center", + paddingTop: 8, + paddingLeft: 73, + paddingRight: 7, + }, + + replyginMsgContainer: { + flex: 1, + marginRight: 5, + overflowY: "hidden", + backgroundColor: "rgba(0, 0, 0, 0.05)", + borderRadius: "7.5px", + display: "flex", + position: "relative", + }, + + replyginMsgBody: { + padding: 10, + height: "auto", + display: "block", + whiteSpace: "pre-wrap", + overflow: "hidden", + }, + + replyginContactMsgSideColor: { + flex: "none", + width: "4px", + backgroundColor: "#35cd96", + }, + + replyginSelfMsgSideColor: { + flex: "none", + width: "4px", + backgroundColor: "#6bcbef", + }, + + messageContactName: { + display: "flex", + color: "#6bcbef", + fontWeight: 500, + }, +})); + +const MessageInput = ({ ticketStatus }) => { + const classes = useStyles(); + const { ticketId } = useParams(); + + const [medias, setMedias] = useState([]); + const [inputMessage, setInputMessage] = useState(""); + const [showEmoji, setShowEmoji] = useState(false); + const [loading, setLoading] = useState(false); + const [recording, setRecording] = useState(false); + const inputRef = useRef(); + const { setReplyingMessage, replyingMessage } = useContext( + ReplyMessageContext + ); + const { user } = useContext(AuthContext); + + const [signMessage, setSignMessage] = useLocalStorage("signOption", true); + + useEffect(() => { + inputRef.current.focus(); + }, [replyingMessage]); + + useEffect(() => { + inputRef.current.focus(); + return () => { + setInputMessage(""); + setShowEmoji(false); + setMedias([]); + setReplyingMessage(null); + }; + }, [ticketId, setReplyingMessage]); + + const handleChangeInput = e => { + setInputMessage(e.target.value); + }; + + const { + selectedMessages, + setForwardMessageModalOpen, + showSelectMessageCheckbox } = useContext(ForwardMessageContext); + + + const handleAddEmoji = e => { + let emoji = e.native; + setInputMessage(prevState => prevState + emoji); + }; + + const handleChangeMedias = e => { + if (!e.target.files) { + return; + } + + const selectedMedias = Array.from(e.target.files); + setMedias(selectedMedias); + }; + + const handleOpenModalForward = () => { + if (selectedMessages.length === 0) { + setForwardMessageModalOpen(false) + toastError(i18n.t("messagesList.header.notMessage")); + return; + } + setForwardMessageModalOpen(true); + } + + const handleInputPaste = e => { + if (e.clipboardData.files[0]) { + setMedias([e.clipboardData.files[0]]); + } + }; + + const handleUploadMedia = async e => { + setLoading(true); + e.preventDefault(); + + const formData = new FormData(); + formData.append("fromMe", true); + medias.forEach(media => { + formData.append("medias", media); + formData.append("body", media.name); + }); + + try { + await api.post(`/messages/${ticketId}`, formData); + } catch (err) { + toastError(err); + } + + setLoading(false); + setMedias([]); + }; + + + + const handleSendMessage = async () => { + if (inputMessage.trim() === "") return; + setLoading(true); + + const message = { + read: 1, + fromMe: true, + mediaUrl: "", + body: signMessage + ? `*${user?.name}:*\n${inputMessage.trim()}` + : inputMessage.trim(), + quotedMsg: replyingMessage, + }; + try { + await api.post(`/messages/${ticketId}`, message); + } catch (err) { + toastError(err); + } + + setInputMessage(""); + setShowEmoji(false); + setLoading(false); + setReplyingMessage(null); + }; + + const handleStartRecording = async () => { + setLoading(true); + try { + await navigator.mediaDevices.getUserMedia({ audio: true }); + await Mp3Recorder.start(); + setRecording(true); + setLoading(false); + } catch (err) { + toastError(err); + setLoading(false); + } + }; + + const handleUploadAudio = async () => { + setLoading(true); + try { + const [, blob] = await Mp3Recorder.stop().getMp3(); + if (blob.size < 10000) { + setLoading(false); + setRecording(false); + return; + } + + const formData = new FormData(); + const filename = `${new Date().getTime()}.mp3`; + formData.append("medias", blob, filename); + formData.append("body", filename); + formData.append("fromMe", true); + + await api.post(`/messages/${ticketId}`, formData); + } catch (err) { + toastError(err); + } + + setRecording(false); + setLoading(false); + }; + + const handleCancelAudio = async () => { + try { + await Mp3Recorder.stop().getMp3(); + setRecording(false); + } catch (err) { + toastError(err); + } + }; + + const renderReplyingMessage = message => { + return ( +
+
+ +
+ {!message.fromMe && ( + + {message.contact?.name} + + )} + {message.body} +
+
+ setReplyingMessage(null)} + > + + +
+ ); + }; + + if (medias.length > 0) + return ( + + setMedias([])} + > + + + + {loading ? ( +
+ +
+ ) : ( + + {medias[0]?.name} + {/* */} + + )} + + + +
+ ); + else { + return ( + + {replyingMessage && renderReplyingMessage(replyingMessage)} +
+ setShowEmoji(prevState => !prevState)} + > + + + {showEmoji ? ( +
+ +
+ ) : null} + + + + { + setSignMessage(e.target.checked); + }} + name="showAllTickets" + color="primary" + /> + } + /> +
+ { + input && input.focus(); + input && (inputRef.current = input); + }} + className={classes.messageInput} + placeholder={ + ticketStatus === "open" + ? i18n.t("messagesInput.placeholderOpen") + : i18n.t("messagesInput.placeholderClosed") + } + multiline + maxRows={5} + value={inputMessage} + onChange={handleChangeInput} + disabled={recording || loading || ticketStatus !== "open"} + onPaste={e => { + ticketStatus === "open" && handleInputPaste(e); + }} + onKeyPress={e => { + if (loading || e.shiftKey) return; + else if (e.key === "Enter") { + handleSendMessage(); + } + }} + /> +
+ {inputMessage || showSelectMessageCheckbox ? ( + <> + + {showSelectMessageCheckbox ? + : } + + + ) : recording ? ( +
+ + + + {loading ? ( +
+ +
+ ) : ( + + )} + + + + +
+ ) : ( + + + + )} +
+
+ ); + } +}; + +export default MessageInput; \ No newline at end of file diff --git a/frontend/src/components/MessageInputCustom/ProgressBarCustom.js b/frontend/src/components/MessageInputCustom/ProgressBarCustom.js new file mode 100644 index 0000000..03189a2 --- /dev/null +++ b/frontend/src/components/MessageInputCustom/ProgressBarCustom.js @@ -0,0 +1,38 @@ +import * as React from 'react'; +import LinearProgress, { LinearProgressProps } from '@material-ui/core/LinearProgress'; +import Typography from '@material-ui/core/Typography'; +import Box from '@material-ui/core/Box'; + +function LinearProgressWithLabel(props) { + return ( + + + + + + {`${Math.round( + props.value, + )}%`} + + + ); +} + +export default function LinearWithValueLabel({progress}) { + //const [progress, setProgress] = React.useState(0); + + React.useEffect(() => { + /*const timer = setInterval(() => { + setProgress((prevProgress) => (prevProgress >= 99 ? 99 : prevProgress + 10)); + }, 420); + return () => { + clearInterval(timer); + };*/ + }, [progress]); + + return ( + + + + ); +} \ No newline at end of file diff --git a/frontend/src/components/MessageInputCustom/RecordingTimer.js b/frontend/src/components/MessageInputCustom/RecordingTimer.js new file mode 100644 index 0000000..108cf50 --- /dev/null +++ b/frontend/src/components/MessageInputCustom/RecordingTimer.js @@ -0,0 +1,48 @@ +import React, { useState, useEffect } from "react"; +import { makeStyles } from "@material-ui/core/styles"; + +const useStyles = makeStyles(theme => ({ + timerBox: { + display: "flex", + marginLeft: 10, + marginRight: 10, + alignItems: "center", + }, +})); + +const RecordingTimer = () => { + const classes = useStyles(); + const initialState = { + minutes: 0, + seconds: 0, + }; + const [timer, setTimer] = useState(initialState); + + useEffect(() => { + const interval = setInterval( + () => + setTimer(prevState => { + if (prevState.seconds === 59) { + return { ...prevState, minutes: prevState.minutes + 1, seconds: 0 }; + } + return { ...prevState, seconds: prevState.seconds + 1 }; + }), + 1000 + ); + return () => { + clearInterval(interval); + }; + }, []); + + const addZero = n => { + return n < 10 ? "0" + n : n; + }; + + return ( +
+ {`${addZero(timer.minutes)}:${addZero(timer.seconds)}`} +
+ ); +}; + +export default RecordingTimer; diff --git a/frontend/src/components/MessageInputCustom/index.js b/frontend/src/components/MessageInputCustom/index.js new file mode 100644 index 0000000..f8703d8 --- /dev/null +++ b/frontend/src/components/MessageInputCustom/index.js @@ -0,0 +1,938 @@ +import React, { useState, useEffect, useContext, useRef } from "react"; +import withWidth, { isWidthUp } from "@material-ui/core/withWidth"; +import "emoji-mart/css/emoji-mart.css"; +import { Picker } from "emoji-mart"; +import MicRecorder from "mic-recorder-to-mp3"; +import clsx from "clsx"; +import { isNil } from "lodash"; +import { Reply } from "@material-ui/icons"; +import { makeStyles } from "@material-ui/core/styles"; +import Paper from "@material-ui/core/Paper"; +import InputBase from "@material-ui/core/InputBase"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import { green, grey } from "@material-ui/core/colors"; +import AttachFileIcon from "@material-ui/icons/AttachFile"; +import IconButton from "@material-ui/core/IconButton"; +import MoodIcon from "@material-ui/icons/Mood"; +import SendIcon from "@material-ui/icons/Send"; +import CancelIcon from "@material-ui/icons/Cancel"; +import ClearIcon from "@material-ui/icons/Clear"; +import MicIcon from "@material-ui/icons/Mic"; +import CheckCircleOutlineIcon from "@material-ui/icons/CheckCircleOutline"; +import HighlightOffIcon from "@material-ui/icons/HighlightOff"; +import { FormControlLabel, Switch } from "@material-ui/core"; +import Autocomplete from "@material-ui/lab/Autocomplete"; +import { isString, isEmpty, isObject, has } from "lodash"; + +import { i18n } from "../../translate/i18n"; +import api from "../../services/api"; +import axios from "axios"; + +import RecordingTimer from "./RecordingTimer"; +import { ReplyMessageContext } from "../../context/ReplyingMessage/ReplyingMessageContext"; +import { ForwardMessageContext } from "../../context/ForwarMessage/ForwardMessageContext"; +import { AuthContext } from "../../context/Auth/AuthContext"; +import { useLocalStorage } from "../../hooks/useLocalStorage"; +import toastError from "../../errors/toastError"; + +import Compressor from 'compressorjs'; +import LinearWithValueLabel from "./ProgressBarCustom"; + +import useQuickMessages from "../../hooks/useQuickMessages"; + +const Mp3Recorder = new MicRecorder({ bitRate: 128 }); + +const useStyles = makeStyles((theme) => ({ + mainWrapper: { + backgroundColor: theme.palette.bordabox, //DARK MODE PLW DESIGN// + display: "flex", + flexDirection: "column", + alignItems: "center", + borderTop: "1px solid rgba(0, 0, 0, 0.12)", + }, + + newMessageBox: { + backgroundColor: theme.palette.newmessagebox, //DARK MODE PLW DESIGN// + width: "100%", + display: "flex", + padding: "7px", + alignItems: "center", + }, + + messageInputWrapper: { + padding: 6, + marginRight: 7, + backgroundColor: theme.palette.inputdigita, //DARK MODE PLW DESIGN// + display: "flex", + borderRadius: 20, + flex: 1, + }, + + + messageInput: { + paddingLeft: 10, + flex: 1, + border: "none", + }, + + sendMessageIcons: { + color: "grey", + }, + + ForwardMessageIcons: { + color: grey[700], + transform: 'scaleX(-1)' + }, + + uploadInput: { + display: "none", + }, + + viewMediaInputWrapper: { + display: "flex", + padding: "10px 13px", + position: "relative", + justifyContent: "space-between", + alignItems: "center", + backgroundColor: theme.palette.inputdigita, + borderTop: "1px solid rgba(0, 0, 0, 0.12)", + }, + + emojiBox: { + position: "absolute", + bottom: 63, + width: 40, + borderTop: "1px solid #e8e8e8", + }, + + circleLoading: { + color: green[500], + opacity: "70%", + position: "absolute", + top: "20%", + left: "50%", + marginLeft: -12, + }, + + audioLoading: { + color: green[500], + opacity: "70%", + }, + + recorderWrapper: { + display: "flex", + alignItems: "center", + alignContent: "middle", + }, + + cancelAudioIcon: { + color: "red", + }, + + sendAudioIcon: { + color: "green", + }, + + replyginMsgWrapper: { + display: "flex", + width: "100%", + alignItems: "center", + justifyContent: "center", + paddingTop: 8, + paddingLeft: 73, + paddingRight: 7, + }, + + replyginMsgContainer: { + flex: 1, + marginRight: 5, + overflowY: "hidden", + backgroundColor: "rgba(0, 0, 0, 0.05)", + borderRadius: "7.5px", + display: "flex", + position: "relative", + }, + + replyginMsgBody: { + padding: 10, + height: "auto", + display: "block", + whiteSpace: "pre-wrap", + overflow: "hidden", + }, + + replyginContactMsgSideColor: { + flex: "none", + width: "4px", + backgroundColor: "#35cd96", + }, + + replyginSelfMsgSideColor: { + flex: "none", + width: "4px", + backgroundColor: "#6bcbef", + }, + + messageContactName: { + display: "flex", + color: "#6bcbef", + fontWeight: 500, + }, +})); + +const EmojiOptions = (props) => { + const { disabled, showEmoji, setShowEmoji, handleAddEmoji } = props; + const classes = useStyles(); + return ( + <> + setShowEmoji((prevState) => !prevState)} + > + + + {showEmoji ? ( +
+ +
+ ) : null} + + ); +}; + +const SignSwitch = (props) => { + const { width, setSignMessage, signMessage } = props; + if (isWidthUp("md", width)) { + return ( + { + setSignMessage(e.target.checked); + }} + name="showAllTickets" + color="primary" + /> + } + /> + ); + } + return null; +}; + +const FileInput = (props) => { + const { handleChangeMedias, disableOption } = props; + const classes = useStyles(); + return ( + <> + + + + ); +}; + +const ActionButtons = (props) => { + const { + inputMessage, + loading, + recording, + ticketStatus, + handleSendMessage, + handleCancelAudio, + handleUploadAudio, + handleStartRecording, + handleOpenModalForward, + showSelectMessageCheckbox + } = props; + const classes = useStyles(); + if (inputMessage || showSelectMessageCheckbox) { + return ( + + {showSelectMessageCheckbox ? + : } + ); +} else if (recording) { + return ( +
+ + + + {loading ? ( +
+ +
+ ) : ( + + )} + + + + +
+ ); + } else { + return ( + + + + ); + } +}; + +const CustomInput = (props) => { + const { + loading, + inputRef, + ticketStatus, + inputMessage, + setInputMessage, + handleSendMessage, + handleInputPaste, + disableOption, + handleQuickAnswersClick, + replyingMessage + } = props; + const classes = useStyles(); + const [quickMessages, setQuickMessages] = useState([]); + const [options, setOptions] = useState([]); + const [popupOpen, setPopupOpen] = useState(false); + const { user } = useContext(AuthContext); + + const { list: listQuickMessages } = useQuickMessages(); + + useEffect(() => { + async function fetchData() { + const companyId = localStorage.getItem("companyId"); + const messages = await listQuickMessages({ companyId, userId: user.id }); + const options = messages.map((m) => { + let truncatedMessage = m.message; + if (isString(truncatedMessage) && truncatedMessage.length > 35) { + truncatedMessage = m.message.substring(0, 35) + "..."; + } + return { + value: m.message, + label: `/${m.shortcode} - ${truncatedMessage}`, + mediaPath: m.mediaPath, + }; + }); + setQuickMessages(options); + } + fetchData(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + +useEffect(() => { + if ( + isString(inputMessage) && + !isEmpty(inputMessage) && + inputMessage.length > 0 + ) { + const firstChar = inputMessage.charAt(0); + setPopupOpen(firstChar === "/"); + + if (firstChar === "/") { + const filteredOptions = quickMessages.filter((m) => + m.label.toLowerCase().startsWith(inputMessage.slice(1).toLowerCase()) + ); + setOptions(filteredOptions); + } else { + setOptions([]); + } + } else { + setPopupOpen(false); + setOptions([]); + } + // eslint-disable-next-line react-hooks/exhaustive-deps +}, [inputMessage]); + + const onKeyPress = (e) => { + if (loading || e.shiftKey) return; + else if (e.key === "Enter") { + handleSendMessage(); + } + }; + + const onPaste = (e) => { + if (ticketStatus === "open") { + handleInputPaste(e); + } + }; + + const renderPlaceholder = () => { + if (ticketStatus === "open") { + return i18n.t("messagesInput.placeholderOpen"); + } + return i18n.t("messagesInput.placeholderClosed"); + }; + + + const setInputRef = (input) => { + if (input) { + input.focus(); + inputRef.current = input; + } + }; + + return ( +
+ { + if (isObject(option)) { + return option.label; + } else { + return option; + } + }} + onChange={(event, opt) => { + + if (isObject(opt) && has(opt, "value") && isNil(opt.mediaPath)) { + setInputMessage(opt.value); + setTimeout(() => { + inputRef.current.scrollTop = inputRef.current.scrollHeight; + }, 200); + } else if (isObject(opt) && has(opt, "value") && !isNil(opt.mediaPath)) { + handleQuickAnswersClick(opt); + + setTimeout(() => { + inputRef.current.scrollTop = inputRef.current.scrollHeight; + }, 200); + } + }} + onInputChange={(event, opt, reason) => { + if (reason === "input") { + setInputMessage(event.target.value); + } + }} + onPaste={onPaste} + onKeyPress={onKeyPress} + style={{ width: "100%" }} + renderInput={(params) => { + const { InputLabelProps, InputProps, ...rest } = params; + return ( + + ); + }} + /> +
+ ); +}; + +const MessageInputCustom = (props) => { + const { ticketStatus, ticketId } = props; + const classes = useStyles(); + const [percentLoading, setPercentLoading] = useState(0); + const [medias, setMedias] = useState([]); + const [inputMessage, setInputMessage] = useState(""); + const [showEmoji, setShowEmoji] = useState(false); + const [loading, setLoading] = useState(false); + const [recording, setRecording] = useState(false); + const inputRef = useRef(); + const { setReplyingMessage, replyingMessage } = + useContext(ReplyMessageContext); + const { user } = useContext(AuthContext); + + const [channelType, setChannelType] = useState(null); + + const [signMessage, setSignMessage] = useLocalStorage("signOption", true); + + const { + selectedMessages, + setForwardMessageModalOpen, + showSelectMessageCheckbox } = useContext(ForwardMessageContext); + + useEffect(() => { + inputRef.current.focus(); + }, [replyingMessage]); + + +useEffect(() => { + const fetchChannelType = async () => { + console.log("Valor atual de ticketId no useEffect:", ticketId); // Log para depuração + if (!ticketId || ticketId === "undefined" || typeof ticketId !== "number") { + console.log("ticketId inválido, ignorando fetchChannelType:", ticketId); + return; + } + try { + const { data } = await api.get(`/tickets/${ticketId}`); + console.log("Dados recebidos do ticket:", data); + console.log("Tipo do canal (whatsapp?.type):", data.whatsapp?.type); + setChannelType(data.whatsapp?.type); + } catch (err) { + console.error("Erro ao buscar o tipo de canal:", err); + toastError(err); + } + }; + fetchChannelType(); +}, [ticketId]); + + useEffect(() => { + inputRef.current.focus(); + return () => { + setInputMessage(""); + setShowEmoji(false); + setMedias([]); + setReplyingMessage(null); + }; + }, [ticketId, setReplyingMessage]); + + + const handleOpenModalForward = () => { + if (selectedMessages.length === 0) { + setForwardMessageModalOpen(false) + toastError(i18n.t("messagesList.header.notMessage")); + return; + } + setForwardMessageModalOpen(true); + } + + const handleAddEmoji = (e) => { + let emoji = e.native; + setInputMessage((prevState) => prevState + emoji); + }; + + const handleChangeMedias = (e) => { + if (!e.target.files) { + return; + } + + const selectedMedias = Array.from(e.target.files); + setMedias(selectedMedias); + }; + + const handleInputPaste = (e) => { + if (e.clipboardData.files[0]) { + setMedias([e.clipboardData.files[0]]); + } + }; + + const handleUploadQuickMessageMedia = async (blob, message) => { + setLoading(true); + try { + const extension = blob.type.split("/")[1]; + + const formData = new FormData(); + const filename = `${new Date().getTime()}.${extension}`; + formData.append("medias", blob, filename); + formData.append("body", message); + formData.append("fromMe", true); + + await api.post(`/messages/${ticketId}`, formData); + } catch (err) { + toastError(err); + setLoading(false); + } + setLoading(false); + }; + + const handleQuickAnswersClick = async (value) => { + if (value.mediaPath) { + try { + const { data } = await axios.get(value.mediaPath, { + responseType: "blob", + }); + + handleUploadQuickMessageMedia(data, value.value); + setInputMessage(""); + return; + // handleChangeMedias(response) + } catch (err) { + toastError(err); + } + } + + setInputMessage(""); + setInputMessage(value.value); + }; + + const handleUploadMedia = async (e) => { + setLoading(true); + e.preventDefault(); + + const formData = new FormData(); + formData.append("fromMe", true); + + if (channelType !== null) { + + medias.forEach((media) => { + formData.append("medias", media); + formData.append("body", media.name); + }); + + }else{ + + medias.forEach(async (media, idx) => { + + const file = media; + + if (!file) { return; } + + if (media?.type.split('/')[0] == 'image') { + new Compressor(file, { + quality: 0.7, + + async success(media) { + + formData.append("medias", media); + formData.append("body", media.name); + + }, + error(err) { + alert('erro') + console.log(err.message); + }, + + }); + } else { + formData.append("medias", media); + formData.append("body", media.name); + + } + + + },); + } + + setTimeout(async()=> { + + try { + + if (channelType !== null) { + await api.post(`/hub-message/${ticketId}`, formData, { + onUploadProgress: (event) => { + let progress = Math.round( + (event.loaded * 100) / event.total + ); + setPercentLoading(progress); + console.log( + `A imagem está ${progress}% carregada... ` + ); + }, + }) + .then((response) => { + setLoading(false) + setMedias([]) + setPercentLoading(0); + console.log( + `A imagem foi enviada para o servidor!` + + ); + }) + .catch((err) => { + console.error( + `Houve um problema ao realizar o upload da imagem.` + ); + console.log(err); + }); + + } else{ + + await api.post(`/messages/${ticketId}`, formData, { + onUploadProgress: (event) => { + let progress = Math.round( + (event.loaded * 100) / event.total + ); + setPercentLoading(progress); + console.log( + `A imagem está ${progress}% carregada... ` + ); + }, + }) + .then((response) => { + setLoading(false) + setMedias([]) + setPercentLoading(0); + console.log( + `A imagem foi enviada para o servidor!` + + ); + }) + .catch((err) => { + console.error( + `Houve um problema ao realizar o upload da imagem.` + ); + console.log(err); + }); + } + + } catch (err) { + toastError(err); + } + + + },2000) + + } + + const handleSendMessage = async () => { + if (inputMessage.trim() === "") return; + setLoading(true); + + const message = { + read: 1, + fromMe: true, + mediaUrl: "", + body: channelType !== null + ? (signMessage + ? `${user?.name}:\n${inputMessage.trim()}` + : inputMessage.trim()) + : (signMessage + ? `*${user?.name}:*\n${inputMessage.trim()}` + : inputMessage.trim()), + quotedMsg: replyingMessage, + companyId: user?.companyId + }; + + try { + + if (channelType !== null) { + await api.post(`/hub-message/${ticketId}`, message); + } else { + await api.post(`/messages/${ticketId}`, message); + } + } catch (err) { + toastError(err); + } + + setInputMessage(""); + setShowEmoji(false); + setLoading(false); + setReplyingMessage(null); + }; + + const handleStartRecording = async () => { + setLoading(true); + try { + await navigator.mediaDevices.getUserMedia({ audio: true }); + await Mp3Recorder.start(); + setRecording(true); + setLoading(false); + } catch (err) { + toastError(err); + setLoading(false); + } + }; + + const handleUploadAudio = async () => { + setLoading(true); + try { + const [, blob] = await Mp3Recorder.stop().getMp3(); + if (blob.size < 10000) { + setLoading(false); + setRecording(false); + return; + } + + const formData = new FormData(); + const filename = `audio-record-site-${new Date().getTime()}.mp3`; + formData.append("medias", blob, filename); + formData.append("body", filename); + formData.append("fromMe", true); + + if (channelType !== null) { + await api.post(`/hub-message/${ticketId}`, formData); + } else { + await api.post(`/messages/${ticketId}`, formData); + } + } catch (err) { + toastError(err); + } + + setRecording(false); + setLoading(false); + }; + + const handleCancelAudio = async () => { + try { + await Mp3Recorder.stop().getMp3(); + setRecording(false); + } catch (err) { + toastError(err); + } + }; + + const disableOption = () => { + return loading || recording || ticketStatus !== "open"; + }; + + const renderReplyingMessage = (message) => { + return ( +
+
+ +
+ {!message.fromMe && ( + + {message.contact?.name} + + )} + {message.body} +
+
+ setReplyingMessage(null)} + > + + +
+ ); + }; + + if (medias.length > 0) + return ( + + setMedias([])} + > + + + + {loading ? ( +
+ {/**/} + +
+ ) : ( + + {medias[0]?.name} + {/* */} + + )} + + + +
+ ); + else { + return ( + + {replyingMessage && renderReplyingMessage(replyingMessage)} +
+ + + + + + + + + +
+
+ ); + } +}; + +export default withWidth()(MessageInputCustom); + diff --git a/frontend/src/components/MessageOptionsMenu/index.js b/frontend/src/components/MessageOptionsMenu/index.js new file mode 100644 index 0000000..83c5f0d --- /dev/null +++ b/frontend/src/components/MessageOptionsMenu/index.js @@ -0,0 +1,281 @@ +import React, { useState, useContext } from "react"; +import PropTypes from "prop-types"; + +import AddCircleOutlineIcon from '@material-ui/icons/Add'; + +import { i18n } from "../../translate/i18n"; +import api from "../../services/api"; +import ConfirmationModal from "../ConfirmationModal"; +import { Menu, MenuItem, MenuList, Grid, Popover, IconButton, makeStyles } from "@material-ui/core"; +import { ReplyMessageContext } from "../../context/ReplyingMessage/ReplyingMessageContext"; +import EditMessageModal from "../EditMessageModal"; +import { ForwardMessageContext } from "../../context/ForwarMessage/ForwardMessageContext"; +import ForwardModal from "../../components/ForwardMessageModal"; +import {toast} from "react-toastify"; +import toastError from "../../errors/toastError"; + +const useStyles = makeStyles((theme) => ({ + iconButton: { + padding: '4px', // Ajuste o valor conforme necessário + }, + gridContainer: { + padding: '10px', + justifyContent: 'center', + }, + addCircleButton: { + padding: '8px', + fontSize: '2rem', // Aumentar o tamanho do ícone + backgroundColor: 'rgb(242 242 247);', + }, + popoverContent: { + maxHeight: '300px', // Ajuste conforme necessário + overflowY: 'auto', + '&::-webkit-scrollbar': { + width: '0.4em', + height: '0.4em', + }, + '&::-webkit-scrollbar-thumb': { + backgroundColor: 'rgba(0,0,0,.1)', + borderRadius: '50px', + }, + '&::-webkit-scrollbar-track': { + boxShadow: 'inset 0 0 6px rgba(0,0,0,0.00)', + webkitBoxShadow: 'inset 0 0 6px rgba(0,0,0,0.00)', + }, + }, + hideScrollbar: { + maxHeight: '300px', + overflow: 'hidden', + }, + })); + +const MessageOptionsMenu = ({ message, menuOpen, handleClose, anchorEl }) => { + const classes = useStyles(); + const { setReplyingMessage } = useContext(ReplyMessageContext); + const [confirmationOpen, setConfirmationOpen] = useState(false); + const [confirmationEditOpen, setEditMessageOpenModal] = useState(false); + const [messageEdit, setMessageEdit] = useState(false); + const [reactionAnchorEl, setReactionAnchorEl] = useState(null); + const [moreAnchorEl, setMoreAnchorEl] = useState(null); + const { + showSelectMessageCheckbox, + setShowSelectMessageCheckbox, + selectedMessages, + forwardMessageModalOpen, + setForwardMessageModalOpen } = useContext(ForwardMessageContext); + + + const handleDeleteMessage = async () => { + try { + await api.delete(`/messages/${message.id}`); + } catch (err) { + toastError(err); + } + }; + + const openReactionsMenu = (event) => { + setReactionAnchorEl(event.currentTarget); + handleClose(); + }; + + const closeReactionsMenu = () => { + setReactionAnchorEl(null); + handleClose(); + }; + + const openMoreReactionsMenu = (event) => { + setMoreAnchorEl(event.currentTarget); + closeReactionsMenu(); // Fechar o primeiro popover + }; + + const closeMoreReactionsMenu = () => { + setMoreAnchorEl(null); + }; + + const handleReactToMessage = async (reactionType) => { + try { + await api.post(`/messages/${message.id}/reactions`, { type: reactionType }); + toast.success(i18n.t("messageOptionsMenu.reactionSuccess")); + } catch (err) { + toastError(err); + } + handleClose(); + closeMoreReactionsMenu(); // Fechar o menu de reações ao reagir + }; + + // Array de emojis + const availableReactions = [ + '😀', '😂', '❤️', '👍', '🎉', '😢', '😮', '😡', '👏', '🔥', + '🥳', '😎', '🤩', '😜', '🤔', '🙄', '😴', '😇', '🤯', '💩', + '🤗', '🤫', '🤭', '🤓', '🤪', '🤥', '🤡', '🤠', '🤢', '🤧', + '😷', '🤕', '🤒', '👻', '💀', '☠️', '👽', '👾', '🤖', '🎃', + '😺', '😸', '😹', '😻', '😼', '😽', '🙀', '😿', '😾', '🙈', + '🙉', '🙊', '🐵', '🐒', '🦍', '🐶', '🐕', '🐩', '🐺', '🦊', + '🦝', '🐱', '🐈', '🦁', '🐯', '🐅', '🐆', '🐴', '🐎', '🦄' + ]; + + const handleSetShowSelectCheckbox = () => { + setShowSelectMessageCheckbox(!showSelectMessageCheckbox); + handleClose(); + }; + + const handleEditMessage = async () => { + try { + await api.put(`/messages/${message.id}`); + } catch (err) { + toastError(err); + } + } + + const hanldeReplyMessage = () => { + setReplyingMessage(message); + handleClose(); + }; + + const handleOpenConfirmationModal = e => { + setConfirmationOpen(true); + handleClose(); + }; + + const handleOpenEditMessageModal = e => { + setEditMessageOpenModal(true); + setMessageEdit(message) + handleClose(); + }; + + return ( + <> + { + setForwardMessageModalOpen(false); + setShowSelectMessageCheckbox(false); + }} + /> + + {i18n.t("messageOptionsMenu.confirmationModal.message")} + + + {i18n.t("messageOptionsMenu.confirmationModal.message")} + + + + {i18n.t("messageOptionsMenu.forward")} + + {message.fromMe && ( + + {i18n.t("messageOptionsMenu.edit")} + + )} + {message.fromMe && ( + + {i18n.t("messageOptionsMenu.delete")} + + )} + + {i18n.t("messageOptionsMenu.reply")} + + + {i18n.t("messageOptionsMenu.react")} + + + +
+ + {availableReactions.slice(0, 6).map(reaction => ( + + handleReactToMessage(reaction)}> + {reaction} + + + ))} + + + + + + +
+
+ +
+ + {availableReactions.map(reaction => ( + + handleReactToMessage(reaction)}> + {reaction} + + + ))} + +
+
+ + ); +}; + +MessageOptionsMenu.propTypes = { + message: PropTypes.object, + menuOpen: PropTypes.bool.isRequired, + handleClose: PropTypes.func.isRequired, + anchorEl: PropTypes.object, + onReaction: PropTypes.func, // Callback opcional chamado após uma reação + availableReactions: PropTypes.arrayOf(PropTypes.string) // Lista opcional de reações disponíveis +} + +export default MessageOptionsMenu; \ No newline at end of file diff --git a/frontend/src/components/MessageVariablesPicker/index.js b/frontend/src/components/MessageVariablesPicker/index.js new file mode 100644 index 0000000..6d6ece2 --- /dev/null +++ b/frontend/src/components/MessageVariablesPicker/index.js @@ -0,0 +1,66 @@ +import React from "react"; +import { Chip, makeStyles } from "@material-ui/core"; +import { i18n } from "../../translate/i18n"; +import OutlinedDiv from "../OutlinedDiv"; + +const useStyles = makeStyles(theme => ({ + chip: { + margin: theme.spacing(0.5), + cursor: "pointer" + } +})); + +const MessageVariablesPicker = ({ onClick, disabled }) => { + const classes = useStyles(); + + const handleClick = (e, value) => { + e.preventDefault(); + if (disabled) return; + onClick(value); + }; + + const msgVars = [ + { + name: i18n.t("messageVariablesPicker.vars.contactFirstName"), + value: "{{firstName}}" + }, + { + name: i18n.t("messageVariablesPicker.vars.contactName"), + value: "{{name}} " + }, + { + name: i18n.t("messageVariablesPicker.vars.greeting"), + value: "{{ms}} " + }, + { + name: i18n.t("messageVariablesPicker.vars.protocolNumber"), + value: "{{protocol}} " + }, + { + name: i18n.t("messageVariablesPicker.vars.hour"), + value: "{{hora}} " + }, + ]; + + return ( + + {msgVars.map(msgVar => ( + handleClick(e, msgVar.value)} + label={msgVar.name} + size="small" + className={classes.chip} + color="primary" + /> + ))} + + ); +}; + +export default MessageVariablesPicker; \ No newline at end of file diff --git a/frontend/src/components/MessagesList/SelectMessageCheckbox.js b/frontend/src/components/MessagesList/SelectMessageCheckbox.js new file mode 100644 index 0000000..eb73bd8 --- /dev/null +++ b/frontend/src/components/MessagesList/SelectMessageCheckbox.js @@ -0,0 +1,33 @@ +import React, { useContext, useEffect } from "react"; +import { Checkbox } from "@mui/material"; +import { ForwardMessageContext } from "../../context/ForwarMessage/ForwardMessageContext"; + +const SelectMessageCheckbox = ({ message }) => { + const { showSelectMessageCheckbox, selectedMessages, setSelectedMessages, resetSelection } = useContext(ForwardMessageContext); + + // Verifica se a mensagem está na lista de selecionadas + const isChecked = selectedMessages.some((m) => m.id === message.id); + + const handleSelectMessage = (e) => { + const updatedList = e.target.checked + ? [...selectedMessages, message] // Adiciona mensagem se marcada + : selectedMessages.filter((m) => m.id !== message.id); // Remove mensagem se desmarcada + + setSelectedMessages(updatedList); + }; + + // Reseta o checkbox quando o resetSelection é chamado + useEffect(() => { + if (!showSelectMessageCheckbox) { + setSelectedMessages([]); // Limpa a seleção se o checkbox for ocultado + } + }, [showSelectMessageCheckbox, setSelectedMessages]); + + if (!showSelectMessageCheckbox) { + return null; + } + + return ; +}; + +export default SelectMessageCheckbox; diff --git a/frontend/src/components/MessagesList/VcardPreview.jsx b/frontend/src/components/MessagesList/VcardPreview.jsx new file mode 100644 index 0000000..f5a6cbc --- /dev/null +++ b/frontend/src/components/MessagesList/VcardPreview.jsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { parse } from 'vcard-parser'; +const vcardStyle = { + backgroundColor: '#f9f9f9', + border: '1px solid #ddd', + borderRadius: '8px', + padding: '20px', + width: '300px', + margin: '20px auto', +}; + +const infoStyle = { + margin: '5px 0', +}; + +const VcardPreview = ({ messageBody }) => { + console.log('messageBody', messageBody); + const vcardObject = parse(messageBody); + const contact = vcardObject.FN; + const number = vcardObject.TEL.value; + return ( +
+

Preview do Cartão de Contato

+
+

Nome: {contact}

+

Número de WhatsApp: {number}

+
+
+ ); +}; + +export default VcardPreview; diff --git a/frontend/src/components/MessagesList/index.js b/frontend/src/components/MessagesList/index.js new file mode 100644 index 0000000..8bf0892 --- /dev/null +++ b/frontend/src/components/MessagesList/index.js @@ -0,0 +1,990 @@ +import React, { useState, useEffect, useReducer, useRef, useContext } from "react"; + +import { isSameDay, parseISO, format } from "date-fns"; +import clsx from "clsx"; + +import { green } from "@material-ui/core/colors"; +import { + Button, + CircularProgress, + Divider, + IconButton, + makeStyles, + Badge, +} from "@material-ui/core"; + +import { + AccessTime, + Block, + Done, + DoneAll, + ExpandMore, + GetApp, + Reply, +} from "@material-ui/icons"; + +import AudioModal from "../AudioModal"; +import MarkdownWrapper from "../MarkdownWrapper"; +import ModalImageCors from "../ModalImageCors"; +import MessageOptionsMenu from "../MessageOptionsMenu"; +import whatsBackground from "../../assets/wa-background.png"; +import LocationPreview from "../LocationPreview"; +import whatsBackgroundDark from "../../assets/wa-background-dark.png"; //DARK MODE PLW DESIGN// +import VCardPreview from "../VCardPreview"; +import api from "../../services/api"; +import toastError from "../../errors/toastError"; +import { SocketContext } from "../../context/Socket/SocketContext"; +import { ForwardMessageContext } from "../../context/ForwarMessage/ForwardMessageContext"; +import { ReplyMessageContext } from "../../context/ReplyingMessage/ReplyingMessageContext"; +import SelectMessageCheckbox from "./SelectMessageCheckbox"; + +const useStyles = makeStyles((theme) => ({ + messagesListWrapper: { + overflow: "hidden", + position: "relative", + display: "flex", + flexDirection: "column", + flexGrow: 1, + width: "100%", + minWidth: 300, + minHeight: 200, + }, + + messagesList: { + backgroundImage: theme.mode === 'light' ? `url(${whatsBackground})` : `url(${whatsBackgroundDark})`, //DARK MODE PLW DESIGN// + display: "flex", + flexDirection: "column", + flexGrow: 1, + padding: "20px 20px 20px 20px", + overflowY: "scroll", + ...theme.scrollbarStyles, + }, + + circleLoading: { + color: green[500], + position: "absolute", + opacity: "70%", + top: 0, + left: "50%", + marginTop: 12, + }, + relationContainer: { + marginTop: -10, + paddingTop: 5, + fontSize: "12px", + color: "#666", + display: "block", + textAlign: "left", + }, + messageLeft: { + marginRight: 20, + marginTop: 2, + minWidth: 100, + maxWidth: 600, + height: "auto", + display: "block", + position: "relative", + "&:hover #messageActionsButton": { + display: "flex", + position: "absolute", + top: 0, + right: 0, + }, + + whiteSpace: "pre-wrap", + backgroundColor: "#ffffff", + color: "#303030", + alignSelf: "flex-start", + borderTopLeftRadius: 0, + borderTopRightRadius: 8, + borderBottomLeftRadius: 8, + borderBottomRightRadius: 8, + paddingLeft: 5, + paddingRight: 5, + paddingTop: 5, + paddingBottom: 0, + boxShadow: "0 1px 1px #b3b3b3", + }, + + quotedContainerLeft: { + margin: "-3px -80px 6px -6px", + overflow: "hidden", + backgroundColor: "#f0f0f0", + borderRadius: "7.5px", + display: "flex", + position: "relative", + }, + + quotedMsg: { + padding: 10, + maxWidth: 300, + height: "auto", + display: "block", + whiteSpace: "pre-wrap", + overflow: "hidden", + }, + + quotedSideColorLeft: { + flex: "none", + width: "4px", + backgroundColor: "#6bcbef", + }, + + messageRight: { + marginLeft: 20, + marginTop: 2, + minWidth: 100, + maxWidth: 600, + height: "auto", + display: "block", + position: "relative", + "&:hover #messageActionsButton": { + display: "flex", + position: "absolute", + top: 0, + right: 0, + }, + + whiteSpace: "pre-wrap", + backgroundColor: "#dcf8c6", + color: "#303030", + alignSelf: "flex-end", + borderTopLeftRadius: 8, + borderTopRightRadius: 8, + borderBottomLeftRadius: 8, + borderBottomRightRadius: 0, + paddingLeft: 5, + paddingRight: 5, + paddingTop: 5, + paddingBottom: 0, + boxShadow: "0 1px 1px #b3b3b3", + }, + + quotedContainerRight: { + margin: "-3px -80px 6px -6px", + overflowY: "hidden", + backgroundColor: "#cfe9ba", + borderRadius: "7.5px", + display: "flex", + position: "relative", + }, + + quotedMsgRight: { + padding: 10, + maxWidth: 300, + height: "auto", + whiteSpace: "pre-wrap", + }, + + quotedSideColorRight: { + flex: "none", + width: "4px", + backgroundColor: "#35cd96", + }, + + messageActionsButton: { + display: "none", + position: "relative", + color: "#999", + zIndex: 1, + backgroundColor: "inherit", + opacity: "90%", + "&:hover, &.Mui-focusVisible": { backgroundColor: "inherit" }, + }, + + messageContactName: { + display: "flex", + color: "#6bcbef", + fontWeight: 500, + }, + + textContentItem: { + overflowWrap: "break-word", + padding: "3px 80px 6px 6px", + }, + + textContentItemEdited: { + overflowWrap: "break-word", + padding: "3px 120px 6px 6px", + }, + + textContentItemDeleted: { + fontStyle: "italic", + color: "rgba(0, 0, 0, 0.36)", + overflowWrap: "break-word", + padding: "3px 80px 6px 6px", + }, + forwardMessage: { + fontSize: 12, + fontStyle: "italic", + position: "absolute", + top: 0, + left: 5, + color: "#999", + display: "flex", + alignItems: "center" + }, + messageMedia: { + objectFit: "cover", + width: 250, + height: 200, + borderTopLeftRadius: 8, + borderTopRightRadius: 8, + borderBottomLeftRadius: 8, + borderBottomRightRadius: 8, + }, + + timestamp: { + fontSize: 11, + position: "absolute", + bottom: 0, + right: 5, + color: "#999", + }, + + dailyTimestamp: { + alignItems: "center", + textAlign: "center", + alignSelf: "center", + width: "110px", + backgroundColor: "#e1f3fb", + margin: "10px", + borderRadius: "10px", + boxShadow: "0 1px 1px #b3b3b3", + }, + + dailyTimestampText: { + color: "#808888", + padding: 8, + alignSelf: "center", + marginLeft: "0px", + }, + + ackIcons: { + fontSize: 18, + verticalAlign: "middle", + marginLeft: 4, + }, + + deletedIcon: { + fontSize: 18, + verticalAlign: "middle", + marginRight: 4, + }, + + ackDoneAllIcon: { + color: green[500], + fontSize: 18, + verticalAlign: "middle", + marginLeft: 4, + }, + + downloadMedia: { + display: "flex", + alignItems: "center", + justifyContent: "center", + backgroundColor: "inherit", + padding: 10, + }, +})); + +const reducer = (state, action) => { + if (action.type === "LOAD_MESSAGES") { + const messages = action.payload; + const newMessages = []; + + messages.forEach((message) => { + const messageIndex = state.findIndex((m) => m.id === message.id); + if (messageIndex !== -1) { + state[messageIndex] = message; + } else { + newMessages.push(message); + } + }); + + return [...newMessages, ...state]; + } + + if (action.type === "ADD_MESSAGE") { + const newMessage = action.payload; + const messageIndex = state.findIndex((m) => m.id === newMessage.id); + + if (messageIndex !== -1) { + state[messageIndex] = newMessage; + } else { + state.push(newMessage); + } + + return [...state]; + } + + if (action.type === "UPDATE_MESSAGE") { + const messageToUpdate = action.payload; + const messageIndex = state.findIndex((m) => m.id === messageToUpdate.id); + + if (messageIndex !== -1) { + state[messageIndex] = messageToUpdate; + } + + return [...state]; + } + + if (action.type === "RESET") { + return []; + } +}; + +const MessagesList = ({ ticket, ticketId, isGroup }) => { + const classes = useStyles(); + + const [messagesList, dispatch] = useReducer(reducer, []); + const [pageNumber, setPageNumber] = useState(1); + const [hasMore, setHasMore] = useState(false); + const [loading, setLoading] = useState(false); + const lastMessageRef = useRef(); + + const [selectedMessage, setSelectedMessage] = useState({}); + const [anchorEl, setAnchorEl] = useState(null); + const messageOptionsMenuOpen = Boolean(anchorEl); + const currentTicketId = useRef(ticketId); + const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; + const socketManager = useContext(SocketContext); + const { setReplyingMessage } = useContext(ReplyMessageContext); + const { showSelectMessageCheckbox } = useContext(ForwardMessageContext); + + useEffect(() => { + dispatch({ type: "RESET" }); + setPageNumber(1); + + currentTicketId.current = ticketId; + }, [ticketId]); + + useEffect(() => { + setLoading(true); + const delayDebounceFn = setTimeout(() => { + const fetchMessages = async () => { + if (ticketId === undefined) return; + try { + const { data } = await api.get("/messages/" + ticketId, { + params: { pageNumber }, + }); + + if (currentTicketId.current === ticketId) { + dispatch({ type: "LOAD_MESSAGES", payload: data.messages }); + setHasMore(data.hasMore); + setLoading(false); + } + + if (pageNumber === 1 && data.messages.length > 1) { + scrollToBottom(); + } + } catch (err) { + setLoading(false); + toastError(err); + } + }; + fetchMessages(); + }, 500); + return () => { + clearTimeout(delayDebounceFn); + }; + }, [pageNumber, ticketId]); + + useEffect(() => { + const companyId = localStorage.getItem("companyId"); + const socket = socketManager.getSocket(companyId); + + socket.on("ready", () => socket.emit("joinChatBox", `${ticket.id}`)); + + socket.on(`company-${companyId}-appMessage`, (data) => { + if (data.action === "create" && data.message.ticketId === currentTicketId.current) { + dispatch({ type: "ADD_MESSAGE", payload: data.message }); + scrollToBottom(); + } + + if (data.action === "update" && data.message.ticketId === currentTicketId.current) { + dispatch({ type: "UPDATE_MESSAGE", payload: data.message }); + } + }); + + return () => { + socket.disconnect(); + }; + }, [ticketId, ticket, socketManager]); + + const loadMore = () => { + setPageNumber((prevPageNumber) => prevPageNumber + 1); + }; + + const scrollToBottom = () => { + if (lastMessageRef.current) { + lastMessageRef.current.scrollIntoView({}); + } + }; + + const handleScroll = (e) => { + if (!hasMore) return; + const { scrollTop } = e.currentTarget; + + if (scrollTop === 0) { + document.getElementById("messagesList").scrollTop = 1; + } + + if (loading) { + return; + } + + if (scrollTop < 50) { + loadMore(); + } + }; + + const hanldeReplyMessage = (e, message) => { + //if (ticket.status === "open" || ticket.status === "group") { + setAnchorEl(null); + setReplyingMessage(message); + //} + }; + + const handleOpenMessageOptionsMenu = (e, message) => { + setAnchorEl(e.currentTarget); + setSelectedMessage(message); + }; + + const handleCloseMessageOptionsMenu = (e) => { + setAnchorEl(null); + }; + + const checkMessageMedia = (message) => { + console.log(message) + if (message.mediaType === "locationMessage" && message.body.split('|').length >= 2) { + let locationParts = message.body.split('|') + let imageLocation = locationParts[0] + let linkLocation = locationParts[1] + + let descriptionLocation = null + + if (locationParts.length > 2) + descriptionLocation = message.body.split('|')[2] + + return + } else + + if (message.mediaType === "contactMessage") { + let array = message.body.split("\n"); + let obj = []; + let contact = ""; + for (let index = 0; index < array.length; index++) { + const v = array[index]; + let values = v.split(":"); + for (let ind = 0; ind < values.length; ind++) { + if (values[ind].indexOf("+") !== -1) { + obj.push({ number: values[ind] }); + } + if (values[ind].indexOf("FN") !== -1) { + contact = values[ind + 1]; + } + } + } + return + } else + + if (message.mediaType === "image") { + return ; + } else + + if (message.mediaType === "audio") { + return ( + + // + ); + } else + + if (message.mediaType === "video") { + return ( +