diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..a0d218e3 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +node_modules +dist +.env \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..ebcf95c5 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,88 @@ +name: Docker Image CI + +on: + push: + branches: + - main + pull_request: + branches: + - main + + +jobs: + build: + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + + outputs: + ec2_ips: ${{ steps.get_instance_ips.outputs.ips }} + image_version: ${{ steps.image_version.outputs.gitsha }} + + steps: + - uses: actions/checkout@v3 + + - name: Set image version (tag) + id: image_version + run: echo "gitsha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + + - name: login to Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: sarahabuirmeileh + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build the Docker image + run: docker build . --file Dockerfile --tag ghcr.io/sarahabuirmeileh/serve-and-shine:${{ steps.image_version.outputs.gitsha }} + - name: Puplish docker image + run: docker push ghcr.io/sarahabuirmeileh/serve-and-shine:${{ steps.image_version.outputs.gitsha }} + + - name: Get EC2 Instance IPs + id: get_instance_ips + run: | + instances=$(aws ec2 describe-instances --filters "Name=tag:aws:autoscaling:groupName,Values=serve-and-shine-asg" --query 'Reservations[*].Instances[*].[PublicIpAddress]' --output json | jq --compact-output 'flatten') + echo "ips=$instances" >> $GITHUB_OUTPUT + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.AWS_REGION }} + + + deploy: + needs: ["build"] + runs-on: ubuntu-latest + strategy: + matrix: + ip: ${{ fromJson(needs.build.outputs.ec2_ips) }} + steps: + - uses: actions/checkout@v3 + - name: configure docker host + uses: khaledez/configure-docker-host@v1 + with: + host: ${{ matrix.ip }} + user: github + ssh-private-key: ${{ secrets.DEPLOYMENT_KEY }} + - name: login to Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: sarahabuirmeileh + password: ${{ secrets.GITHUB_TOKEN }} + - name: deploy + run: docker compose -f docker-compose-prod.yml up -d + env: + DB_PASSWORD: ${{ secrets.DB_PASSWORD }} + GIT_VERSISON: ${{ needs.build.outputs.image_version }} + SECRET_KEY: ${{ secrets.SECRET_KEY }} + DB_HOST: ${{ secrets.DB_HOST }} + DB_PORT: ${{ secrets.DB_PORT }} + DB_USERNAME: ${{ secrets.DB_USERNAME }} + DB_NAME: ${{ secrets.DB_NAME }} + AWS_BUCKET_NAME: ${{ secrets.AWS_BUCKET_NAME }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.AWS_REGION }} + AWS_CERTIFICATES_BUCKET_NAME: ${{ secrets.AWS_CERTIFICATES_BUCKET_NAME }} + PORT: ${{ secrets.PORT }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index a0d218e3..2aacd589 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ node_modules dist -.env \ No newline at end of file +.env +.env.test +logger \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..19daeb48 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "cSpell.words": [ + "Deregistration" + ] +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..62dc4a32 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM node:20-alpine + +WORKDIR /user/app +COPY package.json package-lock.json ./ + +RUN npm ci + +RUN apk add curl + +ADD . . +RUN npm run build + +HEALTHCHECK --interval=10s --timeout=3s \ + CMD curl -f http://localhost/ || exit 1 + +CMD node --loader ts-node/esm ./dist/app.js \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..034e8480 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,21 @@ +# Security Policy + +## Supported Versions + +Use this section to tell people about which versions of your project are +currently being supported with security updates. + +| Version | Supported | +| ------- | ------------------ | +| 5.1.x | :white_check_mark: | +| 5.0.x | :x: | +| 4.0.x | :white_check_mark: | +| < 4.0 | :x: | + +## Reporting a Vulnerability + +Use this section to tell people how to report a vulnerability. + +Tell them where to go, how often they can expect to get an update on a +reported vulnerability, what to expect if the vulnerability is accepted or +declined, etc. diff --git a/__test__/route.test.js b/__test__/route.test.js new file mode 100644 index 00000000..f4e19d26 --- /dev/null +++ b/__test__/route.test.js @@ -0,0 +1,123 @@ +import "../dist/config.js"; +import express from "express"; +import request from "supertest"; +import { createOrganizationAdmin } from "../dist/src/controllers/organizationAdmin.js"; +import organizationProfileRouter from "../dist/src/routes/organizationProfile.js"; +import organizationAdminRouter from "../dist/src/routes/organizationAdmin.js"; +import volunteerRouter from "../dist/src/routes/volunteer.js"; +import permissionRouter from "../dist/src/routes/permission.js"; +import dataSource from "../dist/src/db/dataSource.js"; +import { deleteOrganizationProfile } from "../dist/src/controllers/OrganizationProfile .js"; +import dotenv from "dotenv"; + +dotenv.config(); +const app = express(); +app.use(express.json()); + +app.use('/organizationProfile', organizationProfileRouter); +app.use("/volunteer", volunteerRouter); +app.use('/organizationAdmin', organizationAdminRouter); +app.use('/permission', permissionRouter); +app.use(express.urlencoded({ extended: false })); + + +beforeAll(async () => { + await dataSource.initialize().then(() => { + console.log('DB connected'); + }).catch(err => { + console.log("DB connection failed", err); + }); +}, 30000); + +afterAll(async () => { + await dataSource.destroy(); +}); + +describe("Organization profile", () => { + it("should Create an Organization profile", async () => { + const org = { + name: "TestName", + description: "..." + }; + + const response = await request(app).post("/organizationProfile").send(org); + + expect(response.status).toBe(201); + + }); +}); + +describe("Register process", () => { + it("should register a Volunteer in app", async () => { + const volunteer = { + name: "Tarteel", + email: "tamimitarteel@gamil.com", + password: "Tarteel123456?", + availableTime: ["Afternoon"], + availableLocation: "Hebron", + availableDays: ["Friday"], + skills: ["softskills"] + }; + + const response = await request(app).post("/volunteer/register").send(volunteer); + + expect(response.status).toBe(201); + }); +}); + +describe("Login process", () => { + it("should login a Volunteer in app", async () => { + const volunteer = { + name: "Tarteel", + email: "tamimitarteel@gamil.com", + id: "......" + }; + + const response = await request(app).post("/volunteer/login").send(volunteer); + + expect(response.status).toBe(201); + }); +}); + +describe("Logout process", () => { + it("should logout a Volunteer in app", async () => { + + const response = await request(app).get("/volunteer/logout"); + + expect(response.status).toBe(200); + }); +}); + +describe("Permission", () => { + it("should get all permissions", async () => { + + const response = await request(app).get("/permission").send(volunteer); + + expect(response.status).toBe(200); + }); +}); + +describe("Organization admin", () => { + it("should create an Organization admin", async () => { + const admin = { + name: "Tarteel", + email: "tamimitarteel@gmail.com", + password: "Tarteel123>>", + organizationId: "60eb3e1b-e7b0-4186-9189-9e860c3164dd" + }; + + const response = await createOrganizationAdmin(admin); + + expect(response.name).toBe("Tarteel"); + }); +}); + +describe("Organization profile", () => { + it("should delete an Organization profile", async () => { + const orgId = "cdcc9407-aa39-4b88-99b8-7ae06378eedf" + + const response = await deleteOrganizationProfile(orgId); + + expect(response).toEqual({"affected": 0, "raw": []}); + }); +}); diff --git a/app.ts b/app.ts index ff680ec4..0150d2bb 100644 --- a/app.ts +++ b/app.ts @@ -1,11 +1,23 @@ import "./config.js" +import swaggerUi from 'swagger-ui-express'; import express from 'express' import dotenv from 'dotenv' import createError from 'http-errors' -import dataSource from './src/db/dataSource.js' +import { initDB } from './src/db/dataSource.js' import logger from 'morgan' +import cookieParser from 'cookie-parser' +import fileUpload from 'express-fileupload'; import indexRouter from "./src/routes/index.js" +import permissionRouter from "./src/routes/permission.js" +import roleRouter from "./src/routes/role.js" +import voluntaryWorkRouter from "./src/routes/voluntaryWork.js" +import organizationAdminRouter from "./src/routes/organizationAdmin.js" +import organizationProfileRouter from "./src/routes/organizationProfile.js" +import volunteerRouter from "./src/routes/volunteer.js" +import { authenticate } from "./src/middleware/auth/authenticate.js" +import { errorHandler } from "./src/middleware/errorHandler/errorHandler.js" +import { swaggerSpec } from "./swaggerConfig.js"; const app = express(); dotenv.config(); @@ -13,36 +25,32 @@ const PORT = process.env.PORT || 3000; app.use(express.json()); app.use(express.urlencoded({ extended: false })); +app.use(cookieParser()); +app.use(fileUpload({ limits: { fileSize: 50 * 1024 * 1024 } })) +app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec)); +app.get("/health", function (req, res) { + res.sendStatus(200); +}) app.use('/', indexRouter); -// app.use('/users', usersRouter); +app.use('/permission', authenticate, permissionRouter); +app.use('/role', authenticate, roleRouter); +app.use('/voluntaryWork', authenticate, voluntaryWorkRouter); +app.use('/organizationAdmin', organizationAdminRouter); +app.use('/organizationProfile', authenticate, organizationProfileRouter); +app.use("/volunteer", volunteerRouter); // catch 404 and forward to error handler app.use(function (req, res, next) { - next(createError(404)); + next(createError(404, "The page")); }); - -// error handler -app.use(function (err: any, req: any, res: any, next: any) { - // set locals, only providing error in development - res.locals.message = err.message; - res.locals.error = req.app.get('env') === 'development' ? err : {}; - - // render the error page - res.status(err.status || 500).send({ error: err.message }); -}); - -dataSource.initialize().then(() => { - console.log("Connected to DB!"); -}).catch(err => { - console.error('Failed to connect to DB: ' + err); -}); +app.use(errorHandler); app.listen(PORT, () => { logger(`App is listening on port ${PORT}`); - console.log(`App is listening on port ${PORT} and host http://localhost:${PORT}`); + console.log(`App is listening on port ${PORT}`); + initDB(); }); - export default app; diff --git a/babel.config.cjs b/babel.config.cjs new file mode 100644 index 00000000..78e5fdd2 --- /dev/null +++ b/babel.config.cjs @@ -0,0 +1 @@ +module.exports = { presets: ["@babel/preset-env"] }; \ No newline at end of file diff --git a/docker-compose-prod.yml b/docker-compose-prod.yml new file mode 100644 index 00000000..6d96150a --- /dev/null +++ b/docker-compose-prod.yml @@ -0,0 +1,44 @@ +version: '3' + +services: + # mysql: + # image: mysql + # environment: + # - MYSQL_ROOT_PASSWORD=$DB_PASSWORD + # - MYSQL_DATABASE=$DB_NAME + # volumes: + # - db-data:/var/lib/mysql + # ports: + # - "3306:3306" + # healthcheck: + # test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ] + # timeout: 20s + # retries: 10 + # restart: always + + app: + image: ghcr.io/sarahabuirmeileh/serve-and-shine:$GIT_VERSISON + mem_limit: 5g + restart: always #like sysd service + environment: + - PORT=$PORT + - DB_HOST=$DB_HOST + - DB_USERNAME=$DB_USERNAME + - DB_PASSWORD=$DB_PASSWORD + - DB_NAME=$DB_NAME + - DB_PORT=$DB_PORT + - SECRET_KEY=$SECRET_KEY + - AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY + - AWS_REGION=$AWS_REGION + - AWS_BUCKET_NAME=$AWS_BUCKET_NAME + - AWS_CERTIFICATES_BUCKET_NAME=$AWS_CERTIFICATES_BUCKET_NAME + + ports: + - "80:80" +# depends_on: +# mysql: +# condition: service_healthy + +# volumes: +# db-data: diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..776ae24e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,36 @@ +version: "3" + +services: + # mysql: + # container_name: db + # image: mysql + # environment: + # - MYSQL_ROOT_PASSWORD=$DB_PASSWORD + # - MYSQL_DATABASE=$DB_NAME + # volumes: + # - db-data:/var/lib/mysql + # ports: + # - "3306:3306" + # healthcheck: + # test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ] + # timeout: 20s + # retries: 10 + + app: + container_name: app-docker + build: . + environment: + - PORT=$PORT + - DB_HOST=$DB_HOST + - DB_USERNAME=$DB_USERNAME + - DB_PASSWORD=$DB_PASSWORD + - DB_NAME=$DB_NAME + - DB_PORT=$DB_PORT + - SECRET_KEY=$SECRET_KEY + - AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY + - AWS_REGION=$AWS_REGION + - AWS_BUCKET_NAME=$AWS_BUCKET_NAME + - AWS_CERTIFICATES_BUCKET_NAME=$AWS_CERTIFICATES_BUCKET_NAME + ports: + - "3000:80" \ No newline at end of file diff --git a/infrastructure/setup-instance.sh b/infrastructure/setup-instance.sh new file mode 100644 index 00000000..78a03fba --- /dev/null +++ b/infrastructure/setup-instance.sh @@ -0,0 +1,35 @@ +#!/bin/sh +set -e + +sudo apt update +sudo apt upgrade -y + +sudo apt-get install -y ca-certificates curl gnupg +sudo install -m 0755 -d /etc/apt/keyrings + +# install docker +for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done + +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg +sudo chmod a+r /etc/apt/keyrings/docker.gpg +# Add the repository to Apt sources: +echo \ + "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ + "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null +sudo apt update + +sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + +# create github user +sudo mkdir -p /home/app +sudo useradd --no-create-home --home-dir /home/app --shell /bin/bash github +sudo usermod --append --groups docker github +sudo usermod --append --groups docker ubuntu +sudo chown github:github -R /home/app + +github_pubkey='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPEK4RSwxCZXQRUmzXpsx7xvtSOhcBhZCt2OcvB2gox6 211027@ppu.edu.ps' + +sudo -u github sh -c "mkdir -p /home/app/.ssh && echo $github_pubkey > /home/app/.ssh/authorized_keys" + +sudo reboot \ No newline at end of file diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000..e60b7a90 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,15 @@ +export default { + preset: "ts-jest", + transform: { + "^.+\\.(ts|tsx)?$": "ts-jest", + "^.+\\.(js|jsx)$": "babel-jest", + }, + moduleDirectories: ["node_modules", "src"], + moduleNameMapper: { + "~src/(.*)": "/src/$1", + }, + moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], + transformIgnorePatterns: [ + "node_modules/(?!(jest-)?@?react-native|@react-native-community|@react-navigation|aws-amplify-react-native|@ui-kitten)", + ], +}; \ No newline at end of file diff --git a/logger.ts b/logger.ts new file mode 100644 index 00000000..998bdf21 --- /dev/null +++ b/logger.ts @@ -0,0 +1,12 @@ +import winston from "winston"; + +const baseLogger = winston.createLogger({ + format: winston.format.json(), + defaultMeta: { project: 'serve and shine', time: new Date() }, + transports: [ + new winston.transports.File({ filename: 'logger/error.log', level: 'error' }), + //new winston.transports.File({ filename: 'logger/all.log' }), + ], +}); + +export default baseLogger; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a1c675a8..5544f076 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,1469 +8,7806 @@ "name": "serve-and-shine", "version": "1.0.0", "dependencies": { + "@aws-sdk/client-cloudwatch": "^3.427.0", + "@aws-sdk/client-ses": "^3.429.0", + "@types/express-fileupload": "^1.4.2", + "aws-sdk": "^2.1476.0", "bcrypt": "^5.1.1", + "cookie-parser": "^1.4.6", "debug": "~2.6.9", "dotenv": "^16.3.1", + "email-validator": "^2.0.4", "express": "^4.18.2", + "express-fileupload": "^1.4.1", + "html-pdf": "^3.0.1", "http-errors": "~1.6.3", "jade": "~1.11.0", "jsonwebtoken": "^9.0.2", "morgan": "^1.10.0", - "mysql": "^2.18.1", + "mysql2": "^3.6.1", + "puppeteer": "^21.3.8", + "supertest": "^6.3.3", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.0", "typeorm": "^0.3.17", - "typescript": "^5.2.2" + "uuid": "^9.0.1", + "winston": "^3.11.0" }, "devDependencies": { + "@babel/preset-env": "^7.22.20", + "@types/aws-lambda": "^8.10.124", "@types/bcrypt": "^5.0.0", - "@types/express": "^4.17.17", + "@types/cookie-parser": "^1.4.5", + "@types/express": "^4.17.20", + "@types/html-pdf": "^3.0.2", + "@types/jest": "^29.5.5", "@types/jsonwebtoken": "^9.0.2", "@types/morgan": "^1.9.6", "@types/node": "^20.5.6", + "@types/swagger-jsdoc": "^6.0.2", + "@types/swagger-ui-express": "^4.1.5", + "@types/uuid": "^9.0.5", "concurrently": "^8.2.1", - "nodemon": "^3.0.1" + "jest": "^29.7.0", + "nodemon": "^3.0.1", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.1", + "typescript": "^5.2.2" } }, - "node_modules/@babel/runtime": { - "version": "7.23.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz", - "integrity": "sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==", + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, "dependencies": { - "regenerator-runtime": "^0.14.0" + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0.0" } }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", + "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", "dependencies": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" } }, - "node_modules/@sqltools/formatter": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", - "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" + "node_modules/@apidevtools/json-schema-ref-parser/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, - "node_modules/@types/bcrypt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz", - "integrity": "sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw==", - "dev": true, + "node_modules/@apidevtools/json-schema-ref-parser/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dependencies": { - "@types/node": "*" + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@types/body-parser": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz", - "integrity": "sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" + "node_modules/@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "engines": { + "node": ">=10" } }, - "node_modules/@types/connect": { - "version": "3.4.36", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", - "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", - "dev": true, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==" + }, + "node_modules/@apidevtools/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", "dependencies": { - "@types/node": "*" + "@apidevtools/json-schema-ref-parser": "^9.0.6", + "@apidevtools/openapi-schemas": "^2.0.4", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "call-me-maybe": "^1.0.1", + "z-schema": "^5.0.1" + }, + "peerDependencies": { + "openapi-types": ">=7" } }, - "node_modules/@types/express": { - "version": "4.17.18", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.18.tgz", - "integrity": "sha512-Sxv8BSLLgsBYmcnGdGjjEjqET2U+AKAdCRODmMiq02FgjwuV75Ut85DRpvFjyw/Mk0vgUOliGRU0UUmuuZHByQ==", - "dev": true, + "node_modules/@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" } }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.37", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.37.tgz", - "integrity": "sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==", - "dev": true, + "node_modules/@aws-crypto/crc32/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/ie11-detection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" + "tslib": "^1.11.1" } }, - "node_modules/@types/http-errors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.2.tgz", - "integrity": "sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==", - "dev": true + "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", - "integrity": "sha512-b0jGiOgHtZ2jqdPgPnP6WLCXZk1T8p06A/vPGzUvxpFGgKMbjXJDjC5m52ErqBnIuWZFgGoIJyRdeG5AyreJjA==", - "dev": true, + "node_modules/@aws-crypto/sha256-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", "dependencies": { - "@types/node": "*" + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" } }, - "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true + "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/@types/morgan": { - "version": "1.9.6", - "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.6.tgz", - "integrity": "sha512-xfKogz5WcKww2DAiVT9zxMgrqQt+Shq8tDVeLT+otoj6dJnkRkyJxMF51mHtUc3JCPKGk5x1EBU0buuGpfftlQ==", - "dev": true, + "node_modules/@aws-crypto/sha256-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", "dependencies": { - "@types/node": "*" + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" } }, - "node_modules/@types/node": { - "version": "20.7.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.0.tgz", - "integrity": "sha512-zI22/pJW2wUZOVyguFaUL1HABdmSVxpXrzIqkjsHmyUjNhPoWM1CKfvVuXfetHhIok4RY573cqS0mZ1SJEnoTg==", - "dev": true + "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/@types/qs": { - "version": "6.9.8", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", - "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", - "dev": true + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "dependencies": { + "tslib": "^1.11.1" + } }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true + "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/@types/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.2.tgz", - "integrity": "sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==", - "dev": true, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "node_modules/@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/util/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-sdk/client-cloudwatch": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch/-/client-cloudwatch-3.433.0.tgz", + "integrity": "sha512-CDrwPWege1M2r49qEbyyBLe2C7aODAr1k//dLVUqQY+4K/n7SDlE5aI25FI3q07xH82tD3SCDxRwpohE+ypsjg==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.433.0", + "@aws-sdk/credential-provider-node": "3.433.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.433.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.433.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "@smithy/util-waiter": "^2.0.12", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-ses": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.433.0.tgz", + "integrity": "sha512-sRzljw21cKDJAYLRX8L/6pI9AwTRj48lND8rVFOZHdKQOszpG/N84e7thDp+RaM2ynPd4Wd5tOIFtJ1Jj5BMMw==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.433.0", + "@aws-sdk/credential-provider-node": "3.433.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.433.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.433.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "@smithy/util-waiter": "^2.0.12", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.433.0.tgz", + "integrity": "sha512-L7ksMP7UnYH+w52ly+m+s5vk8662VtyqJ+UduFEMPqKUHTFEm7w+CCw4Xfk3hl5GlVvqPvYWqBqv8eLKSHpCEQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.433.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.433.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.433.0.tgz", + "integrity": "sha512-hQ+NLIcA1KRJ2qPdrtkJ3fOEVnehLLMlnB/I5mjg9K2UKjuiOufLao6tc5SyW9fseIL9AdX3fjJ8Unhg+y1RWg==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/credential-provider-node": "3.433.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-sdk-sts": "3.433.0", + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.433.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.433.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.433.0.tgz", + "integrity": "sha512-Vl7Qz5qYyxBurMn6hfSiNJeUHSqfVUlMt0C1Bds3tCkl3IzecRWwyBOlxtxO3VCrgVeW3HqswLzCvhAFzPH6nQ==", + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.433.0.tgz", + "integrity": "sha512-T+YhCOORyA4+i4T86FfFCmi/jPsmLOP6GAtScHp/K8XzB9XuVvJSZ+T8SUKeW6/9G9z3Az7dqeBVLcMdC6fFDA==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.433.0", + "@aws-sdk/credential-provider-process": "3.433.0", + "@aws-sdk/credential-provider-sso": "3.433.0", + "@aws-sdk/credential-provider-web-identity": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@types/serve-static": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.3.tgz", - "integrity": "sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==", - "dev": true, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.433.0.tgz", + "integrity": "sha512-uOTBJszqGJIX5SrH2YdN501cv9rW4ghuSkasxI9DL+sVV5YRMd/bwu6I3PphRyK7z4dosDEbJ1xoIuVR/W04HQ==", "dependencies": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" + "@aws-sdk/credential-provider-env": "3.433.0", + "@aws-sdk/credential-provider-ini": "3.433.0", + "@aws-sdk/credential-provider-process": "3.433.0", + "@aws-sdk/credential-provider-sso": "3.433.0", + "@aws-sdk/credential-provider-web-identity": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.433.0.tgz", + "integrity": "sha512-W7FcGlQjio9Y/PepcZGRyl5Bpwb0uWU7qIUCh+u4+q2mW4D5ZngXg8V/opL9/I/p4tUH9VXZLyLGwyBSkdhL+A==", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">= 0.6" + "node": ">=14.0.0" } }, - "node_modules/acorn": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", - "integrity": "sha512-pXK8ez/pVjqFdAgBkF1YPVRacuLQ9EXBKaKWaeh58WNfMkCmZhOZzu+NtKSPD5PHmCCHheQ5cD29qM1K4QTxIg==", - "bin": { - "acorn": "bin/acorn" + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.433.0.tgz", + "integrity": "sha512-vuc2X7q/1HUAO/NowfnNMpRDoHw8H2lyZZzUc0lmamy6PDrEFBi/VTm1nStGPuS9egCFrYlkRHsfp50ukYGa5w==", + "dependencies": { + "@aws-sdk/client-sso": "3.433.0", + "@aws-sdk/token-providers": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">=0.4.0" + "node": ">=14.0.0" } }, - "node_modules/acorn-globals": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz", - "integrity": "sha512-j3/4pkfih8W4NK22gxVSXcEonTpAHOHh0hu5BoZrKcOsW/4oBPxTi4Yk3SAj+FhC1f3+bRTkXdm4019gw1vg9g==", + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.433.0.tgz", + "integrity": "sha512-RlwjP1I5wO+aPpwyCp23Mk8nmRbRL33hqRASy73c4JA2z2YiRua+ryt6MalIxehhwQU6xvXUKulJnPG9VaMFZg==", "dependencies": { - "acorn": "^2.1.0" + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "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==", + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.433.0.tgz", + "integrity": "sha512-mBTq3UWv1UzeHG+OfUQ2MB/5GEkt5LTKFaUqzL7ESwzW8XtpBgXnjZvIwu3Vcd3sEetMwijwaGiJhY0ae/YyaA==", "dependencies": { - "debug": "4" + "@aws-sdk/types": "3.433.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">= 6.0.0" + "node": ">=14.0.0" } }, - "node_modules/agent-base/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.433.0.tgz", + "integrity": "sha512-We346Fb5xGonTGVZC9Nvqtnqy74VJzYuTLLiuuftA5sbNzftBDy/22QCfvYSTOAl3bvif+dkDUzQY2ihc5PwOQ==", "dependencies": { - "ms": "2.1.2" + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=14.0.0" } }, - "node_modules/agent-base/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/align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==", + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.433.0.tgz", + "integrity": "sha512-HEvYC9PQlWY/ccUYtLvAlwwf1iCif2TSAmLNr3YTBRVa98x6jKL0hlCrHWYklFeqOGSKy6XhE+NGJMUII0/HaQ==", "dependencies": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" + "@aws-sdk/types": "3.433.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=14.0.0" } }, - "node_modules/amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "node_modules/@aws-sdk/middleware-sdk-sts": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.433.0.tgz", + "integrity": "sha512-ORYbJnBejUyonFl5FwIqhvI3Cq6sAp9j+JpkKZtFNma9tFPdrhmYgfCeNH32H/wGTQV/tUoQ3luh0gA4cuk6DA==", + "dependencies": { + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=0.4.2" + "node": ">=14.0.0" } }, - "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==", + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.433.0.tgz", + "integrity": "sha512-jxPvt59NZo/epMNLNTu47ikmP8v0q217I6bQFGJG7JVFnfl36zDktMwGw+0xZR80qiK47/2BWrNpta61Zd2FxQ==", + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.433.0.tgz", + "integrity": "sha512-jMgA1jHfisBK4oSjMKrtKEZf0sl2vzADivkFmyZFzORpSZxBnF6hC21RjaI+70LJLcc9rSCzLgcoz5lHb9LLDg==", "dependencies": { - "color-convert": "^2.0.1" + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=14.0.0" } }, - "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==" - }, - "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==", - "dev": true, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.433.0.tgz", + "integrity": "sha512-xpjRjCZW+CDFdcMmmhIYg81ST5UAnJh61IHziQEk0FXONrg4kjyYPZAOjEdzXQ+HxJQuGQLKPhRdzxmQnbX7pg==", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" }, "engines": { - "node": ">= 8" + "node": ">=14.0.0" } }, - "node_modules/app-root-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", - "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "node_modules/@aws-sdk/token-providers": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.433.0.tgz", + "integrity": "sha512-Q6aYVaQKB+CkBLHQQlN8MHVpOzZv9snRfVz7SxIpdbHkRuGEHiLliCY3fg6Sonvu3AKEPERPuHcaC75tnNpOBw==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.433.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, "engines": { - "node": ">= 6.0.0" + "node": ">=14.0.0" } }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + "node_modules/@aws-sdk/types": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.433.0.tgz", + "integrity": "sha512-0jEE2mSrNDd8VGFjTc1otYrwYPIkzZJEIK90ZxisKvQ/EURGBhNzWn7ejWB9XCMFT6XumYLBR0V9qq5UPisWtA==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.433.0.tgz", + "integrity": "sha512-LFNUh9FH7RMtYjSjPGz9lAJQMzmJ3RcXISzc5X5k2R/9mNwMK7y1k2VAfvx+RbuDbll6xwsXlgv6QHcxVdF2zw==", "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" + "@aws-sdk/types": "3.433.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">=10" + "node": ">=14.0.0" } }, - "node_modules/are-we-there-yet/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==", + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "tslib": "^2.5.0" }, "engines": { - "node": ">= 6" + "node": ">=14.0.0" } }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "node_modules/asap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz", - "integrity": "sha512-Ej9qjcXY+8Tuy1cNqiwNMwFRXOy9UwgTeMA8LxreodygIPV48lx8PU1ecFxb5ZeU1DpMKxiq6vGLTxcitWZPbA==" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.433.0.tgz", + "integrity": "sha512-2Cf/Lwvxbt5RXvWFXrFr49vXv0IddiUwrZoAiwhDYxvsh+BMnh+NUFot+ZQaTrk/8IPZVDeLPWZRdVy00iaVXQ==", + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + } }, - "node_modules/basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.433.0.tgz", + "integrity": "sha512-yT1tO4MbbsUBLl5+S+jVv8wxiAtP5TKjKib9B2KQ2x0OtWWTrIf2o+IZK8va+zQqdV4MVMjezdxdE20hOdB4yQ==", "dependencies": { - "safe-buffer": "5.1.2" + "@aws-sdk/types": "3.433.0", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">= 0.8" + "node": ">=14.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } } }, - "node_modules/basic-auth/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "dependencies": { + "tslib": "^2.3.1" + } }, - "node_modules/bcrypt": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", - "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", - "hasInstallScript": true, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.11", - "node-addon-api": "^5.0.0" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { - "node": ">= 10.0.0" + "node": ">=6.9.0" } }, - "node_modules/bignumber.js": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", - "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, "engines": { - "node": "*" + "node": ">=4" } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "node_modules/@babel/code-frame/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==", "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "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.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/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==" + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=0.8.0" } }, - "node_modules/body-parser/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "has-flag": "^3.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=4" } }, - "node_modules/body-parser/node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node_modules/@babel/compat-data": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/@babel/core": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.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": ">=8" + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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/@babel/core/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "node_modules/@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==", "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==", + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, "dependencies": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" + "@babel/types": "^7.22.5" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@babel/types": "^7.22.15" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/character-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-1.2.1.tgz", - "integrity": "sha512-6OEBVBlf/y8LaAphnbAnt743O3zMhlBer+FO5D40H6wqAdU9B1TvuApkejgLW0cvv0tEZNLktv1AnRI+C87ueQ==" + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz", + "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "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" + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" }, "engines": { - "node": ">= 8.10.0" + "node": ">=6.9.0" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "engines": { - "node": ">=10" + "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==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/clean-css": { - "version": "3.4.28", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", - "integrity": "sha512-aTWyttSdI2mYi07kWqHi24NUU9YlELFKGOAgFzZjDN1064DMAOy2FBuoyGmkKRlXkbpXd0EVHmiVkbKhKoirTw==", + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "dev": true, "dependencies": { - "commander": "2.8.x", - "source-map": "0.4.x" - }, - "bin": { - "cleancss": "bin/cleancss" + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/clean-css/node_modules/commander": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "integrity": "sha512-+pJLBFVk+9ZZdlAOB5WuIElVPPth47hILFkmGym57aq8kwxsowvByvB0DHs1vQAhyMZzdcpTtF0VDKGkSDR4ZQ==", + "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==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz", + "integrity": "sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==", + "dev": true, "dependencies": { - "graceful-readlink": ">= 1.0.0" + "@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" }, - "engines": { - "node": ">= 0.6.x" + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/cli-highlight": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", - "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "dependencies": { - "chalk": "^4.0.0", - "highlight.js": "^10.7.1", - "mz": "^2.4.0", - "parse5": "^5.1.1", - "parse5-htmlparser2-tree-adapter": "^6.0.0", - "yargs": "^16.0.0" + "ms": "2.1.2" }, - "bin": { - "highlight": "bin/highlight" + "engines": { + "node": ">=6.0" }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" + "node": ">=6.9.0" } }, - "node_modules/cli-highlight/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==", + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/cli-highlight/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, "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" + "@babel/types": "^7.22.5" }, "engines": { - "node": ">=10" + "node": ">=6.9.0" } }, - "node_modules/cli-highlight/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==", + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0" + }, "engines": { - "node": ">=10" + "node": ">=6.9.0" } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "@babel/types": "^7.22.15" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dev": true, "dependencies": { - "color-name": "~1.1.4" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { - "node": ">=7.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "bin": { - "color-support": "bin.js" + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/commander": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz", - "integrity": "sha512-PhbTMT+ilDXZKqH8xbvuUY2ZEQNef0Q7DKxgoEKb4ccytsdvVVJmYqR0sGbi96nxU6oGrwEIQnclpK2NBZuQlg==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, "engines": { - "node": ">= 0.6.x" + "node": ">=6.9.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==" - }, - "node_modules/concurrently": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.1.tgz", - "integrity": "sha512-nVraf3aXOpIcNud5pB9M82p1tynmZkrSGQ1p6X/VY8cJ+2LMVqAgXsJxYYefACSHbTYlm92O1xuhdGTjwoEvbQ==", + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", "dev": true, "dependencies": { - "chalk": "^4.1.2", - "date-fns": "^2.30.0", - "lodash": "^4.17.21", - "rxjs": "^7.8.1", - "shell-quote": "^1.8.1", - "spawn-command": "0.0.2", - "supports-color": "^8.1.1", - "tree-kill": "^1.2.2", - "yargs": "^17.7.2" + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" }, - "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" }, "engines": { - "node": "^14.13.0 || >=16.0.0" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/constantinople": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.0.2.tgz", - "integrity": "sha512-UnEggAQrmhxuTxlb7n1OsTtagNXWUv2CRlOogZhWOU4jLK4EJEbF8UDSNxuGu+jVtWNtO2j51ab2H1wlBIzF/w==", - "deprecated": "Please update to at least constantinople 3.1.1", + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dev": true, "dependencies": { - "acorn": "^2.1.0" + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, "dependencies": { - "safe-buffer": "5.2.1" + "@babel/types": "^7.22.5" }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" } }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" } }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/core-util-is": { + "node_modules/@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", + "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/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==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/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==" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.22.15", + "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.22.15.tgz", + "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz", + "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", + "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", + "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/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==", + "dev": true, + "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.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", + "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.2.tgz", + "integrity": "sha512-BBYVGxbDVHfoeXbOwcagAkOQAm9NxoTdMGfTqghu1GrvadSaw6iW3Je6IcL5PNOw8VwjxqBECXy50/iCQSY/lQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", + "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", + "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz", + "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", + "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz", + "integrity": "sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz", + "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-split-export-declaration": "^7.22.6", + "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.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", + "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz", + "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", + "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", + "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz", + "integrity": "sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", + "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz", + "integrity": "sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz", + "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", + "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz", + "integrity": "sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", + "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz", + "integrity": "sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", + "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz", + "integrity": "sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", + "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz", + "integrity": "sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", + "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", + "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz", + "integrity": "sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@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-transform-numeric-separator": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz", + "integrity": "sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz", + "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", + "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz", + "integrity": "sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz", + "integrity": "sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz", + "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", + "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz", + "integrity": "sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-plugin-utils": "^7.22.5", + "@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-transform-property-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", + "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", + "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", + "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", + "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", + "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", + "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", + "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", + "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", + "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", + "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", + "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", + "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.2.tgz", + "integrity": "sha512-BW3gsuDD+rvHL2VO2SjAUNTBe5YrjsTiDyqamPDWY723na3/yPQ65X5oQkFVJZ0o50/2d+svm1rkPoJeR1KxVQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.2", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@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/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.22.5", + "@babel/plugin-transform-async-generator-functions": "^7.23.2", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/plugin-transform-block-scoped-functions": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.23.0", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-class-static-block": "^7.22.11", + "@babel/plugin-transform-classes": "^7.22.15", + "@babel/plugin-transform-computed-properties": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.23.0", + "@babel/plugin-transform-dotall-regex": "^7.22.5", + "@babel/plugin-transform-duplicate-keys": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.11", + "@babel/plugin-transform-exponentiation-operator": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.11", + "@babel/plugin-transform-for-of": "^7.22.15", + "@babel/plugin-transform-function-name": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.11", + "@babel/plugin-transform-literals": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.11", + "@babel/plugin-transform-member-expression-literals": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.23.0", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-modules-systemjs": "^7.23.0", + "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-numeric-separator": "^7.22.11", + "@babel/plugin-transform-object-rest-spread": "^7.22.15", + "@babel/plugin-transform-object-super": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.23.0", + "@babel/plugin-transform-parameters": "^7.22.15", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.11", + "@babel/plugin-transform-property-literals": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.10", + "@babel/plugin-transform-reserved-words": "^7.22.5", + "@babel/plugin-transform-shorthand-properties": "^7.22.5", + "@babel/plugin-transform-spread": "^7.22.5", + "@babel/plugin-transform-sticky-regex": "^7.22.5", + "@babel/plugin-transform-template-literals": "^7.22.5", + "@babel/plugin-transform-typeof-symbol": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.10", + "@babel/plugin-transform-unicode-property-regex": "^7.22.5", + "@babel/plugin-transform-unicode-regex": "^7.22.5", + "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "@babel/types": "^7.23.0", + "babel-plugin-polyfill-corejs2": "^0.4.6", + "babel-plugin-polyfill-corejs3": "^0.8.5", + "babel-plugin-polyfill-regenerator": "^0.5.3", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "node_modules/@babel/runtime": { + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz", + "integrity": "sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "devOptional": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "devOptional": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", + "dev": true, + "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.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "devOptional": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "devOptional": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@puppeteer/browsers": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.8.0.tgz", + "integrity": "sha512-TkRHIV6k2D8OlUe8RtG+5jgOF/H98Myx0M6AOafC8DdNVOFiBSFa5cpRDtpm8LXOa9sVwe0+e6Q3FC56X/DZfg==", + "dependencies": { + "debug": "4.3.4", + "extract-zip": "2.0.1", + "progress": "2.0.3", + "proxy-agent": "6.3.1", + "tar-fs": "3.0.4", + "unbzip2-stream": "1.4.3", + "yargs": "17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=16.3.0" + } + }, + "node_modules/@puppeteer/browsers/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@puppeteer/browsers/node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/@puppeteer/browsers/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@puppeteer/browsers/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/@puppeteer/browsers/node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.12.tgz", + "integrity": "sha512-YIJyefe1mi3GxKdZxEBEuzYOeQ9xpYfqnFmWzojCssRAuR7ycxwpoRQgp965vuW426xUAQhCV5rCaWElQ7XsaA==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.16.tgz", + "integrity": "sha512-1k+FWHQDt2pfpXhJsOmNMmlAZ3NUQ98X5tYsjQhVGq+0X6cOBMhfh6Igd0IX3Ut6lEO6DQAdPMI/blNr3JZfMQ==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.18.tgz", + "integrity": "sha512-QnPBi6D2zj6AHJdUTo5zXmk8vwHJ2bNevhcVned1y+TZz/OI5cizz5DsYNkqFUIDn8tBuEyKNgbmKVNhBbuY3g==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/property-provider": "^2.0.13", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.12.tgz", + "integrity": "sha512-ZZQLzHBJkbiAAdj2C5K+lBlYp/XJ+eH2uy+jgJgYIFW/o5AM59Hlj7zyI44/ZTDIQWmBxb3EFv/c5t44V8/g8A==", + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-hex-encoding": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.4.tgz", + "integrity": "sha512-gIPRFEGi+c6V52eauGKrjDzPWF2Cu7Z1r5F8A3j2wcwz25sPG/t8kjsbEhli/tS/2zJp/ybCZXe4j4ro3yv/HA==", + "dependencies": { + "@smithy/protocol-http": "^3.0.8", + "@smithy/querystring-builder": "^2.0.12", + "@smithy/types": "^2.4.0", + "@smithy/util-base64": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.12.tgz", + "integrity": "sha512-fDZnTr5j9t5qcbeJ037aMZXxMka13Znqwrgy3PAqYj6Dm3XHXHftTH3q+NWgayUxl1992GFtQt1RuEzRMy3NnQ==", + "dependencies": { + "@smithy/types": "^2.4.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.12.tgz", + "integrity": "sha512-p5Y+iMHV3SoEpy3VSR7mifbreHQwVSvHSAz/m4GdoXfOzKzaYC8hYv10Ks7Deblkf7lhas8U+lAp9ThbBM+ZXA==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", + "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.14.tgz", + "integrity": "sha512-poUNgKTw9XwPXfX9nEHpVgrMNVpaSMZbshqvPxFVoalF4wp6kRzYKOfdesSVectlQ51VtigoLfbXcdyPwvxgTg==", + "dependencies": { + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.1.3.tgz", + "integrity": "sha512-ZrQ0/YX6hNVTxqMEHtEaDbDv6pNeEji/a5Vk3HuFC5R3ZY8lfoATyxmOGxBVYnF3NUvZLNC7umEv1WzWGWvCGQ==", + "dependencies": { + "@smithy/middleware-serde": "^2.0.12", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/shared-ini-file-loader": "^2.2.2", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.18.tgz", + "integrity": "sha512-VyrHQRldGSb3v9oFOB5yPxmLT7U2sQic2ytylOnYlnsmVOLlFIaI6sW22c+w2675yq+XZ6HOuzV7x2OBYCWRNA==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/protocol-http": "^3.0.8", + "@smithy/service-error-classification": "^2.0.5", + "@smithy/types": "^2.4.0", + "@smithy/util-middleware": "^2.0.5", + "@smithy/util-retry": "^2.0.5", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-retry/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/@smithy/middleware-serde": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.12.tgz", + "integrity": "sha512-IBeco157lIScecq2Z+n0gq56i4MTnfKxS7rbfrAORveDJgnbBAaEQgYqMqp/cYqKrpvEXcyTjwKHrBjCCIZh2A==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.6.tgz", + "integrity": "sha512-YSvNZeOKWLJ0M/ycxwDIe2Ztkp6Qixmcml1ggsSv2fdHKGkBPhGrX5tMzPGMI1yyx55UEYBi2OB4s+RriXX48A==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.3.tgz", + "integrity": "sha512-J6lXvRHGVnSX3n1PYi+e1L5HN73DkkJpUviV3Ebf+8wSaIjAf+eVNbzyvh/S5EQz7nf4KVfwbD5vdoZMAthAEQ==", + "dependencies": { + "@smithy/property-provider": "^2.0.13", + "@smithy/shared-ini-file-loader": "^2.2.2", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.8.tgz", + "integrity": "sha512-KZylM7Wff/So5SmCiwg2kQNXJ+RXgz34wkxS7WNwIUXuZrZZpY/jKJCK+ZaGyuESDu3TxcaY+zeYGJmnFKbQsA==", + "dependencies": { + "@smithy/abort-controller": "^2.0.12", + "@smithy/protocol-http": "^3.0.8", + "@smithy/querystring-builder": "^2.0.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.13.tgz", + "integrity": "sha512-VJqUf2CbsQX6uUiC5dUPuoEATuFjkbkW3lJHbRnpk9EDC9X+iKqhfTK+WP+lve5EQ9TcCI1Q6R7hrg41FyC54w==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.8.tgz", + "integrity": "sha512-SHJvYeWq8q0FK8xHk+xjV9dzDUDjFMT+G1pZbV+XB6OVoac/FSVshlMNPeUJ8AmSkcDKHRu5vASnRqZHgD3qhw==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.12.tgz", + "integrity": "sha512-cDbF07IuCjiN8CdGvPzfJjXIrmDSelScRfyJYrYBNBbKl2+k7QD/KqiHhtRyEKgID5mmEVrV6KE6L/iPJ98sFw==", + "dependencies": { + "@smithy/types": "^2.4.0", + "@smithy/util-uri-escape": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.12.tgz", + "integrity": "sha512-fytyTcXaMzPBuNtPlhj5v6dbl4bJAnwKZFyyItAGt4Tgm9HFPZNo7a9r1SKPr/qdxUEBzvL9Rh+B9SkTX3kFxg==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.5.tgz", + "integrity": "sha512-M0SeJnEgD2ywJyV99Fb1yKFzmxDe9JfpJiYTVSRMyRLc467BPU0qsuuDPzMCdB1mU8M8u1rVOdkqdoyFN8UFTw==", + "dependencies": { + "@smithy/types": "^2.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.2.tgz", + "integrity": "sha512-noyQUPn7b1M8uB0GEXc/Zyxq+5K2b7aaqWnLp+hgJ7+xu/FCvtyWy5eWLDjQEsHnAet2IZhS5QF8872OR69uNg==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.12.tgz", + "integrity": "sha512-6Kc2lCZEVmb1nNYngyNbWpq0d82OZwITH11SW/Q0U6PX5fH7B2cIcFe7o6eGEFPkTZTP8itTzmYiGcECL0D0Lw==", + "dependencies": { + "@smithy/eventstream-codec": "^2.0.12", + "@smithy/is-array-buffer": "^2.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "@smithy/util-uri-escape": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.12.tgz", + "integrity": "sha512-XXqhridfkKnpj+lt8vM6HRlZbqUAqBjVC74JIi13F/AYQd/zTj9SOyGfxnbp4mjY9q28LityxIuV8CTinr9r5w==", + "dependencies": { + "@smithy/middleware-stack": "^2.0.6", + "@smithy/types": "^2.4.0", + "@smithy/util-stream": "^2.0.17", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.4.0.tgz", + "integrity": "sha512-iH1Xz68FWlmBJ9vvYeHifVMWJf82ONx+OybPW8ZGf5wnEv2S0UXcU4zwlwJkRXuLKpcSLHrraHbn2ucdVXLb4g==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.12.tgz", + "integrity": "sha512-qgkW2mZqRvlNUcBkxYB/gYacRaAdck77Dk3/g2iw0S9F0EYthIS3loGfly8AwoWpIvHKhkTsCXXQfzksgZ4zIA==", + "dependencies": { + "@smithy/querystring-parser": "^2.0.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-base64": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.0.tgz", + "integrity": "sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==", + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", + "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", + "dependencies": { + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", + "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", + "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "dependencies": { + "@smithy/is-array-buffer": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", + "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.16.tgz", + "integrity": "sha512-Uv5Cu8nVkuvLn0puX+R9zWbSNpLIR3AxUlPoLJ7hC5lvir8B2WVqVEkJLwtixKAncVLasnTVjPDCidtAUTGEQw==", + "dependencies": { + "@smithy/property-provider": "^2.0.13", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.21.tgz", + "integrity": "sha512-cUEsttVZ79B7Al2rWK2FW03HBpD9LyuqFtm+1qFty5u9sHSdesr215gS2Ln53fTopNiPgeXpdoM3IgjvIO0rJw==", + "dependencies": { + "@smithy/config-resolver": "^2.0.16", + "@smithy/credential-provider-imds": "^2.0.18", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/property-provider": "^2.0.13", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", + "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.5.tgz", + "integrity": "sha512-1lyT3TcaMJQe+OFfVI+TlomDkPuVzb27NZYdYtmSTltVmLaUjdCyt4KE+OH1CnhZKsz4/cdCL420Lg9UH5Z2Mw==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.5.tgz", + "integrity": "sha512-x3t1+MQAJ6QONk3GTbJNcugCFDVJ+Bkro5YqQQK1EyVesajNDqxFtCx9WdOFNGm/Cbm7tUdwVEmfKQOJoU2Vtw==", + "dependencies": { + "@smithy/service-error-classification": "^2.0.5", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.17.tgz", + "integrity": "sha512-fP/ZQ27rRvHsqItds8yB7jerwMpZFTL3QqbQbidUiG0+mttMoKdP0ZqnvM8UK5q0/dfc3/pN7g4XKPXOU7oRWw==", + "dependencies": { + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/types": "^2.4.0", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", + "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", + "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-waiter": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.0.12.tgz", + "integrity": "sha512-3sENmyVa1NnOPoiT2NCApPmu7ukP7S/v7kL9IxNmnygkDldn7/yK0TP42oPJLwB2k3mospNsSePIlqdXEUyPHA==", + "dependencies": { + "@smithy/abort-controller": "^2.0.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@sqltools/formatter": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", + "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "devOptional": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "devOptional": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "devOptional": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "devOptional": true + }, + "node_modules/@types/aws-lambda": { + "version": "8.10.125", + "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.125.tgz", + "integrity": "sha512-Vqw/WMlV4O1fJT6capim01v7VLDZkcX1n6Yhb52E7IfnMqYbNfwHfyDV8rRN42NLBtdDvfaqcCqs2K0fr5ljZw==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", + "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==", + "dev": true, + "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.6", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz", + "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz", + "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.3.tgz", + "integrity": "sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/bcrypt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz", + "integrity": "sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.3", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz", + "integrity": "sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/busboy": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/busboy/-/busboy-1.5.2.tgz", + "integrity": "sha512-OYkRy+dkQWwoGch3oyQ9UE08PO1jSte7aBtPemLXAP9evwh7fNAfikWdB2VMeP8syY3H/XvGq+pB38dDvTe06g==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", + "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie-parser": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.5.tgz", + "integrity": "sha512-cbpH1NldYslPt7WRHXZFm+G7DTfUg57dQSCf1qrHwT8wtGX41JHLYf3Cieiqg7waPWjorVgcSSllZov+A1PJbg==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz", + "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-fileupload": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@types/express-fileupload/-/express-fileupload-1.4.3.tgz", + "integrity": "sha512-DvSXoec9+IcfXJ7qG48yCUKpbyEV5CQAZlGzsh2B8FTvb/MrMq/y2YpuAtnWYyjfqRaooKJL7TxgWIkiPehyqQ==", + "dependencies": { + "@types/busboy": "*", + "@types/express": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.37", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.37.tgz", + "integrity": "sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz", + "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/html-pdf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/html-pdf/-/html-pdf-3.0.2.tgz", + "integrity": "sha512-54ZW4+zCgjV6gq4qxwW12eIvlrulZqYDpHciltpamkX/OwCOPBkNWcyHkhHzd/Z+7ak7x9ZXIv/h/0OYzIX2eA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.2.tgz", + "integrity": "sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz", + "integrity": "sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz", + "integrity": "sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.6", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", + "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==" + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-b0jGiOgHtZ2jqdPgPnP6WLCXZk1T8p06A/vPGzUvxpFGgKMbjXJDjC5m52ErqBnIuWZFgGoIJyRdeG5AyreJjA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "node_modules/@types/morgan": { + "version": "1.9.6", + "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.6.tgz", + "integrity": "sha512-xfKogz5WcKww2DAiVT9zxMgrqQt+Shq8tDVeLT+otoj6dJnkRkyJxMF51mHtUc3JCPKGk5x1EBU0buuGpfftlQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.7.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.0.tgz", + "integrity": "sha512-zI22/pJW2wUZOVyguFaUL1HABdmSVxpXrzIqkjsHmyUjNhPoWM1CKfvVuXfetHhIok4RY573cqS0mZ1SJEnoTg==" + }, + "node_modules/@types/qs": { + "version": "6.9.8", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", + "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/send": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.2.tgz", + "integrity": "sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.3.tgz", + "integrity": "sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.2.tgz", + "integrity": "sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==", + "dev": true + }, + "node_modules/@types/swagger-jsdoc": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.2.tgz", + "integrity": "sha512-Qor3ObrH9Q27VWEiyw2zfE/nNgFCrA3D6Rm8V8fwYeLikfVw4au9Je0F+88QBgeCgMKSoCx12akTEaBqacIHjw==", + "dev": true + }, + "node_modules/@types/swagger-ui-express": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.5.tgz", + "integrity": "sha512-MRvm1OCzIR321glc/4tP34wRVmsupgLzs6XIq50CFp0CJUzxbpDsrhJxEBMQfoO46ixrlCiw3QXxEs5HHxYI8Q==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/triple-beam": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.4.tgz", + "integrity": "sha512-HlJjF3wxV4R2VQkFpKe0YqJLilYNgtRtsqqZtby7RkVsSs+i+vbyzjtUwpFEdUCKcrGzCiEJE7F/0mKjh0sunA==" + }, + "node_modules/@types/uuid": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz", + "integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.29", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz", + "integrity": "sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.2", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.2.tgz", + "integrity": "sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==", + "dev": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.2.tgz", + "integrity": "sha512-Km7XAtUIduROw7QPgvcft0lIupeG8a8rdKL8RiSyKvlE7dYY31fEn41HVuQsRFDuROA8tA4K2UVL+WdfFmErBA==", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "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/acorn": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", + "integrity": "sha512-pXK8ez/pVjqFdAgBkF1YPVRacuLQ9EXBKaKWaeh58WNfMkCmZhOZzu+NtKSPD5PHmCCHheQ5cD29qM1K4QTxIg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz", + "integrity": "sha512-j3/4pkfih8W4NK22gxVSXcEonTpAHOHh0hu5BoZrKcOsW/4oBPxTi4Yk3SAj+FhC1f3+bRTkXdm4019gw1vg9g==", + "dependencies": { + "acorn": "^2.1.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "devOptional": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/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/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "optional": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==", + "dependencies": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "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==" + }, + "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==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/app-root-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "devOptional": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "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/asap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz", + "integrity": "sha512-Ej9qjcXY+8Tuy1cNqiwNMwFRXOy9UwgTeMA8LxreodygIPV48lx8PU1ecFxb5ZeU1DpMKxiq6vGLTxcitWZPbA==" + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "optional": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "optional": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sdk": { + "version": "2.1478.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1478.0.tgz", + "integrity": "sha512-F+Ud9FxMD4rwvGbEXn7qc25Q19N4p+9klRjiH1llFLYssPw6TRtY464Cry/jG4OzuYkE/DsnhcwVFEJjGvMmuQ==", + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "util": "^0.12.4", + "uuid": "8.0.0", + "xml2js": "0.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aws-sdk/node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/aws-sdk/node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/aws-sdk/node_modules/uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "optional": true + }, + "node_modules/b4a": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", + "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==" + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz", + "integrity": "sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.3", + "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==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.5.tgz", + "integrity": "sha512-Q6CdATeAvbScWPNLB8lzSO7fgUVBkQt6zLgNlfyeCr/EQaEQR+bWiBYYPYAFyE528BMjRhL+1QBMOI4jc/c5TA==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.3", + "core-js-compat": "^3.32.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz", + "integrity": "sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.3" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/basic-ftp": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.3.tgz", + "integrity": "sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "optional": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "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.1", + "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/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/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/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "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==", + "devOptional": true + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001551", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001551.tgz", + "integrity": "sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "optional": true + }, + "node_modules/center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==", + "dependencies": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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/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==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/character-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-1.2.1.tgz", + "integrity": "sha512-6OEBVBlf/y8LaAphnbAnt743O3zMhlBer+FO5D40H6wqAdU9B1TvuApkejgLW0cvv0tEZNLktv1AnRI+C87ueQ==" + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "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" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/chromium-bidi": { + "version": "0.4.32", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.32.tgz", + "integrity": "sha512-RJnw0PW3sNdx1WclINVfVVx8JUH+tWTHZNpnEzlcM+Qgvf40dUH34U7gJq+cc/0LE+rbPxeT6ldqWrCbUf4jeg==", + "dependencies": { + "mitt": "3.0.1", + "urlpattern-polyfill": "9.0.0" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/clean-css": { + "version": "3.4.28", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", + "integrity": "sha512-aTWyttSdI2mYi07kWqHi24NUU9YlELFKGOAgFzZjDN1064DMAOy2FBuoyGmkKRlXkbpXd0EVHmiVkbKhKoirTw==", + "dependencies": { + "commander": "2.8.x", + "source-map": "0.4.x" + }, + "bin": { + "cleancss": "bin/cleancss" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-css/node_modules/commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha512-+pJLBFVk+9ZZdlAOB5WuIElVPPth47hILFkmGym57aq8kwxsowvByvB0DHs1vQAhyMZzdcpTtF0VDKGkSDR4ZQ==", + "dependencies": { + "graceful-readlink": ">= 1.0.0" + }, + "engines": { + "node": ">= 0.6.x" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==", + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/cli-highlight/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==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cli-highlight/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "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/cli-highlight/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==", + "engines": { + "node": ">=10" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/color/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==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color/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==" + }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz", + "integrity": "sha512-PhbTMT+ilDXZKqH8xbvuUY2ZEQNef0Q7DKxgoEKb4ccytsdvVVJmYqR0sGbi96nxU6oGrwEIQnclpK2NBZuQlg==", + "engines": { + "node": ">= 0.6.x" + } + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "optional": true, + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/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==", + "optional": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "optional": true + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "optional": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/concurrently": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.1.tgz", + "integrity": "sha512-nVraf3aXOpIcNud5pB9M82p1tynmZkrSGQ1p6X/VY8cJ+2LMVqAgXsJxYYefACSHbTYlm92O1xuhdGTjwoEvbQ==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "date-fns": "^2.30.0", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "spawn-command": "0.0.2", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": "^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/constantinople": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.0.2.tgz", + "integrity": "sha512-UnEggAQrmhxuTxlb7n1OsTtagNXWUv2CRlOogZhWOU4jLK4EJEbF8UDSNxuGu+jVtWNtO2j51ab2H1wlBIzF/w==", + "deprecated": "Please update to at least constantinople 3.1.1", + "dependencies": { + "acorn": "^2.1.0" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "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/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==" + }, + "node_modules/core-js-compat": { + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.1.tgz", + "integrity": "sha512-6pYKNOgD/j/bkC5xS5IIg6bncid3rfrI42oBH1SQJbsmYPKF7rhzcFzYCcxYMmNQQ0rCEB8WqpW7QHndOggaeQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.22.1" + }, + "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==", + "optional": true + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/cosmiconfig/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "devOptional": true + }, + "node_modules/cross-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", + "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz", + "integrity": "sha512-qmTYWhHk910nQWnGqMAiWWPQlB6tESiWgNebQJmiozOAGcBAQ1+U/UzUOkhdrcshlkSRRiKWodwmVvO0OmnIGg==", + "dependencies": { + "css-parse": "1.0.4", + "css-stringify": "1.0.5" + } + }, + "node_modules/css-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz", + "integrity": "sha512-pfstzKVRZiHprDXdsmtfH1HYUEw22lzjuHdnpe1hscwoQvgW2C5zDQIBE0RKoALEReTn9W1ECdY8uaT/kO4VfA==" + }, + "node_modules/css-stringify": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz", + "integrity": "sha512-aIThpcErhG5EyHorGqNlTh0TduNBqLrrXLO3x5rku3ZKBxuVfY+T7noyM2G2X/01iQANqJUb6d3+FLoa+N7Xwg==" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.1.tgz", + "integrity": "sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==", + "engines": { + "node": ">= 14" + } + }, + "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/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/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/devtools-protocol": { + "version": "0.0.1191157", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1191157.tgz", + "integrity": "sha512-Fu2mUhX7zkzLHMJZk5wQTiHdl1eJrhK0GypUoSzogUt51MmYEv/46pCz4PtGGFlr0f2ZyYDzzx5CPtbEkuvcTA==" + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/dezalgo/node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "devOptional": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "optional": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "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/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/electron-to-chromium": { + "version": "1.4.565", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.565.tgz", + "integrity": "sha512-XbMoT6yIvg2xzcbs5hCADi0dXBh4//En3oFXmtPX+jiyyiCTiM9DGFT2SLottjpEs9Z8Mh8SqahbR96MaHfuSg==", + "dev": true + }, + "node_modules/email-validator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz", + "integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ==", + "engines": { + "node": ">4.0" + } + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, + "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/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "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==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "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==", + "optional": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "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/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "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/execa/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "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.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.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/express-fileupload": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.4.1.tgz", + "integrity": "sha512-9F6SkbxbEOA9cYOBZ8tnn238jL+bGfacQuUO/JqPWp5t+piUcoDcESvKwAXsQV7IHGxmI5bMj3QxMWOKOIsMCg==", + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/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/express/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "optional": true + }, + "node_modules/extract-zip": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", + "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "optional": true, + "dependencies": { + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ], + "optional": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "optional": true + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, + "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==", + "devOptional": true + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + }, + "node_modules/fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "optional": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/formidable": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", + "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", + "dependencies": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0", + "qs": "^6.11.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha512-VerQV6vEKuhDWD2HGOybV6v5I73syoc/cXAbKlgTC7M/oFVEtklWlp9QH2Ijw3IaWDOQcMkldSPa7zXy79Z/UQ==", + "optional": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "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==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-uri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.2.tgz", + "integrity": "sha512-5KLucCJobh8vBY1K07EFV4+cPZH3mrV9YeAruUseCQKHB58SGjjT2l9/eA9LD082IiuMjSlFJEcdJ27TXvbZNw==", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.0", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/get-uri/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/get-uri/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/get-uri/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/get-uri/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/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "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": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==" + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "optional": true, + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/css": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz", - "integrity": "sha512-qmTYWhHk910nQWnGqMAiWWPQlB6tESiWgNebQJmiozOAGcBAQ1+U/UzUOkhdrcshlkSRRiKWodwmVvO0OmnIGg==", + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/hasha": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", + "integrity": "sha512-jZ38TU/EBiGKrmyTNNZgnvCZHNowiRI4+w/I9noMlekHTZH3KyGgvJLmhSgykeAQ9j2SYPDosM0Bg3wHfzibAQ==", + "optional": true, + "dependencies": { + "is-stream": "^1.0.1", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "engines": { + "node": ">=8" + } + }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "engines": { + "node": "*" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/html-pdf": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-pdf/-/html-pdf-3.0.1.tgz", + "integrity": "sha512-CKNSacmQn+CKJ2GNfT4UYKaPy/T3Ndj82yJ2aju/UPmnvWNjIpyumqRqkFU0mwT6BTHBFhFGTnXN8dBn4Bdj0Q==", + "deprecated": "Please migrate your projects to a newer library like puppeteer", + "bin": { + "html-pdf": "bin/index.js" + }, + "engines": { + "node": ">=4.0.0" + }, + "optionalDependencies": { + "phantomjs-prebuilt": "^2.1.16" + } + }, + "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==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "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==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.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==", "dependencies": { - "css-parse": "1.0.4", - "css-stringify": "1.0.5" + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/css-parse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz", - "integrity": "sha512-pfstzKVRZiHprDXdsmtfH1HYUEw22lzjuHdnpe1hscwoQvgW2C5zDQIBE0RKoALEReTn9W1ECdY8uaT/kO4VfA==" + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/css-stringify": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz", - "integrity": "sha512-aIThpcErhG5EyHorGqNlTh0TduNBqLrrXLO3x5rku3ZKBxuVfY+T7noyM2G2X/01iQANqJUb6d3+FLoa+N7Xwg==" + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true }, - "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==", + "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==", "dependencies": { - "@babel/runtime": "^7.21.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=0.11" + "node": ">=6" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/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==", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, "dependencies": { - "ms": "2.0.0" + "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/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=0.8.19" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + "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==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } }, - "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==", + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "node_modules/ip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==" + }, + "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.8" + "node": ">= 0.10" } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "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==" + }, + "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==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, "dependencies": { - "safe-buffer": "^5.0.1" + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "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==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, "engines": { "node": ">=6" } }, - "node_modules/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/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "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==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "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==", + "dev": true, "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.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" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">= 0.10.0" + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" } }, - "node_modules/express/node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "optional": true, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/express/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "which-typed-array": "^1.1.11" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/express/node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "optional": true }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "devOptional": true + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "optional": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, "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" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.8" + "node": ">=10" } }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "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==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, "engines": { - "node": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, "dependencies": { - "minipass": "^3.0.0" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "engines": { - "node": ">= 8" + "node": ">=10" } }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "dependencies": { - "yallist": "^4.0.0" + "ms": "2.1.2" }, "engines": { - "node": ">=8" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=8" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "node_modules/jade": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/jade/-/jade-1.11.0.tgz", + "integrity": "sha512-J76sbGKeLtu7uwW97Ntzb1UvGnpKTDplYa9ROr2gNRhM+SxvlBSG0Ees3TQ8+7ya2UVkzMEeFxhRhEpN68s7Tg==", + "deprecated": "Jade has been renamed to pug, please install the latest version of pug instead of jade", + "dependencies": { + "character-parser": "1.2.1", + "clean-css": "^3.1.9", + "commander": "~2.6.0", + "constantinople": "~3.0.1", + "jstransformer": "0.0.2", + "mkdirp": "~0.5.0", + "transformers": "2.1.0", + "uglify-js": "^2.4.19", + "void-elements": "~2.0.1", + "with": "~4.0.0" + }, + "bin": { + "jade": "bin/jade.js" + } }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/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==", + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, "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" + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "engines": { - "node": "*" + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">= 6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==" - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, "dependencies": { - "function-bind": "^1.1.1" + "detect-newline": "^3.0.0" }, "engines": { - "node": ">= 0.4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "engines": { - "node": ">= 0.4" + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, - "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==", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" - }, - "node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, "engines": { - "node": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { - "node": ">= 0.6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/http-errors/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">= 0.6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/http-errors/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, - "node_modules/http-errors/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==", + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">= 0.6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, "dependencies": { - "agent-base": "6", - "debug": "4" + "@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": ">= 6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, "dependencies": { - "ms": "2.1.2" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=6.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" }, "peerDependenciesMeta": { - "supports-color": { + "jest-resolve": { "optional": true } } }, - "node_modules/https-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true - }, - "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==", + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" - }, - "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==", + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, "engines": { - "node": ">= 0.10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "dependencies": { - "binary-extensions": "^2.0.0" + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "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": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "dependencies": { - "is-extglob": "^2.1.1" + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, "engines": { - "node": ">=0.12.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + "node_modules/jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "engines": { + "node": ">= 0.6.0" + } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "node_modules/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/jade": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/jade/-/jade-1.11.0.tgz", - "integrity": "sha512-J76sbGKeLtu7uwW97Ntzb1UvGnpKTDplYa9ROr2gNRhM+SxvlBSG0Ees3TQ8+7ya2UVkzMEeFxhRhEpN68s7Tg==", - "deprecated": "Jade has been renamed to pug, please install the latest version of pug instead of jade", + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, "dependencies": { - "character-parser": "1.2.1", - "clean-css": "^3.1.9", - "commander": "~2.6.0", - "constantinople": "~3.0.1", - "jstransformer": "0.0.2", - "mkdirp": "~0.5.0", - "transformers": "2.1.0", - "uglify-js": "^2.4.19", - "void-elements": "~2.0.1", - "with": "~4.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "optional": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" }, + "engines": { + "node": ">=4" + } + }, + "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==" + }, + "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==", + "optional": true + }, + "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==", + "optional": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "optional": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, "bin": { - "jade": "bin/jade.js" + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", + "optional": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, "node_modules/jsonwebtoken": { @@ -1499,6 +7836,21 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "optional": true, + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/jstransformer": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-0.0.2.tgz", @@ -1527,6 +7879,12 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/kew": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", + "integrity": "sha512-IG6nm0+QtAMdXt9KvbgbGdvY50RSrw+U4sGZg+KlrSKPJEwVE5JVoI3d7RWfSMdBQneRheeAOj3lIjX5VL/9RQ==", + "optional": true + }, "node_modules/kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -1538,6 +7896,29 @@ "node": ">=0.10.0" } }, + "node_modules/klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", + "optional": true, + "optionalDependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, "node_modules/lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", @@ -1546,12 +7927,49 @@ "node": ">=0.10.0" } }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/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==" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "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==", "dev": true }, + "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==", + "dev": true + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" + }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -1562,6 +7980,11 @@ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, "node_modules/lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", @@ -1582,11 +8005,48 @@ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==" + }, "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, + "node_modules/logform": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", + "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/logform/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/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, "node_modules/longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -1596,14 +8056,11 @@ } }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", + "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", "engines": { - "node": ">=10" + "node": ">=16.14" } }, "node_modules/make-dir": { @@ -1628,6 +8085,21 @@ "semver": "bin/semver.js" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "devOptional": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1641,6 +8113,12 @@ "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==", + "dev": true + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -1649,6 +8127,19 @@ "node": ">= 0.6" } }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -1679,6 +8170,15 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1729,6 +8229,11 @@ "node": ">=8" } }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==" + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -1740,6 +8245,11 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, "node_modules/morgan": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", @@ -1771,25 +8281,24 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/mysql": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", - "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "node_modules/mysql2": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.6.2.tgz", + "integrity": "sha512-m5erE6bMoWfPXW1D5UrVwlT8PowAoSX69KcZzPuARQ3wY1RJ52NW9PdvdPo076XiSIkQ5IBTis7hxdlrQTlyug==", "dependencies": { - "bignumber.js": "9.0.0", - "readable-stream": "2.3.7", - "safe-buffer": "5.1.2", - "sqlstring": "2.3.1" + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru-cache": "^8.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" }, "engines": { - "node": ">= 0.6" + "node": ">= 8.0" } }, - "node_modules/mysql/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -1800,6 +8309,31 @@ "thenify-all": "^1.0.0" } }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -1808,6 +8342,14 @@ "node": ">= 0.6" } }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/node-addon-api": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", @@ -1832,6 +8374,18 @@ } } }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, "node_modules/nodemon": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.1.tgz", @@ -1916,69 +8470,273 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "optional": true, + "engines": { + "node": "*" + } + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "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==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dependencies": { + "fn.name": "1.x.x" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "peer": true + }, + "node_modules/optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==", + "dependencies": { + "wordwrap": "~0.0.2" + } + }, + "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==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "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==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" } }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "node_modules/pac-proxy-agent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", + "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "pac-resolver": "^7.0.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" } }, - "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==", + "node_modules/pac-proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dependencies": { + "debug": "^4.3.4" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 14" } }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/pac-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "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==", + "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", "dependencies": { - "ee-first": "1.1.1" + "agent-base": "^7.0.2", + "debug": "4" }, "engines": { - "node": ">= 0.8" + "node": ">= 14" } }, - "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==", + "node_modules/pac-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/pac-resolver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", + "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", + "dependencies": { + "degenerator": "^5.0.0", + "ip": "^1.1.8", + "netmask": "^2.0.2" + }, "engines": { - "node": ">= 0.8" + "node": ">= 14" } }, - "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==", + "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==", "dependencies": { - "wrappy": "1" + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/optimist": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", - "integrity": "sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==", + "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==", "dependencies": { - "wordwrap": "~0.0.2" + "@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": { @@ -2007,6 +8765,15 @@ "node": ">= 0.8" } }, + "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==", + "dev": true, + "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", @@ -2015,11 +8782,73 @@ "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==", + "dev": true, + "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==", + "dev": true + }, "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + }, + "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==", + "optional": true + }, + "node_modules/phantomjs-prebuilt": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", + "integrity": "sha512-PIiRzBhW85xco2fuj41FmsyuYHKjKuXWmhjy3A/Y+CMpN/63TV+s9uzfVhsUwFe0G77xWtHBG8xmXf5BqEUEuQ==", + "deprecated": "this package is now deprecated", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "es6-promise": "^4.0.3", + "extract-zip": "^1.6.5", + "fs-extra": "^1.0.0", + "hasha": "^2.2.0", + "kew": "^0.7.0", + "progress": "^1.1.8", + "request": "^2.81.0", + "request-progress": "^2.0.1", + "which": "^1.2.10" + }, + "bin": { + "phantomjs": "bin/phantomjs" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2032,36 +8861,293 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "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==" - }, - "node_modules/promise": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz", - "integrity": "sha512-O+uwGKreKNKkshzZv2P7N64lk6EP17iXBn0PbUnNQhk+Q0AHLstiTrjkx3v5YBd3cxUe7Sq6KyRhl/A0xUjk7Q==", + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "optional": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "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==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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==", + "optional": true + }, + "node_modules/progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha512-UdA8mJ4weIkUBO224tIarHzuHs4HuYiJvsuGT7j/SPQiUJVjYvNDBIPa0hAorduOfjGohB/qHWRa/lrrWX/mXw==", + "optional": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz", + "integrity": "sha512-O+uwGKreKNKkshzZv2P7N64lk6EP17iXBn0PbUnNQhk+Q0AHLstiTrjkx3v5YBd3cxUe7Sq6KyRhl/A0xUjk7Q==", + "dependencies": { + "asap": "~1.0.0" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "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-agent": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", + "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "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/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "optional": true + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/puppeteer": { + "version": "21.4.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-21.4.1.tgz", + "integrity": "sha512-opJqQeYMjAB3ICG8lCF3wtSs9k05dozmrEMrHgo3ZWbISiy8qbv/yAJz/6Io221qSh3yURfVf6Z7crrlzKZjLQ==", + "hasInstallScript": true, + "dependencies": { + "@puppeteer/browsers": "1.8.0", + "cosmiconfig": "8.3.6", + "puppeteer-core": "21.4.1" + }, + "engines": { + "node": ">=16.3.0" + } + }, + "node_modules/puppeteer-core": { + "version": "21.4.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-21.4.1.tgz", + "integrity": "sha512-Lh0e+oGhUquxVOi1U701gTfFLFvw5gDBFh3CWpnfAvtItmyZKUce4R54VNfOJfi+KKnzhVPdB/lDrg65gdRIng==", "dependencies": { - "asap": "~1.0.0" + "@puppeteer/browsers": "1.8.0", + "chromium-bidi": "0.4.32", + "cross-fetch": "4.0.0", + "debug": "4.3.4", + "devtools-protocol": "0.0.1191157", + "ws": "8.14.2" + }, + "engines": { + "node": ">=16.3.0" } }, - "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==", + "node_modules/puppeteer-core/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "ms": "2.1.2" }, "engines": { - "node": ">= 0.10" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true + "node_modules/puppeteer-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/pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] }, "node_modules/qs": { "version": "6.11.0", @@ -2077,6 +9163,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -2114,30 +9214,41 @@ "node": ">= 0.8" } }, + "node_modules/raw-body/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/raw-body/node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "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" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -2155,11 +9266,76 @@ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" }, + "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==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/regenerator-runtime": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, "node_modules/repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -2168,6 +9344,66 @@ "node": ">=0.10" } }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "optional": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request-progress": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", + "integrity": "sha512-dxdraeZVUNEn9AvLrxkgB2k6buTlym71dJk1fk4v8j3Ou3RKNm07BcgbHdj2lLgYGfqX71F+awb1MR+tWPFJzA==", + "optional": true, + "dependencies": { + "throttleit": "^1.0.0" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "optional": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/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.", + "optional": true, + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -2176,6 +9412,53 @@ "node": ">=0.10.0" } }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -2229,11 +9512,24 @@ } ] }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" + }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -2248,6 +9544,17 @@ "node": ">=10" } }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -2296,6 +9603,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, "node_modules/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -2315,6 +9627,20 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -2332,6 +9658,27 @@ "sha.js": "bin.js" } }, + "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==", + "dev": true, + "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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/shell-quote": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", @@ -2359,6 +9706,19 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", @@ -2368,18 +9728,113 @@ "semver": "^7.5.3" }, "engines": { - "node": ">=10" + "node": ">=10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socks-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/socks/node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, + "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==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==", + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, "dependencies": { - "amdefine": ">=0.0.4" - }, - "engines": { - "node": ">=0.8.0" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, "node_modules/spawn-command": { @@ -2388,14 +9843,65 @@ "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", "dev": true }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, "node_modules/sqlstring": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", - "integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", "engines": { "node": ">= 0.6" } }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "optional": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "engines": { + "node": "*" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -2404,18 +9910,43 @@ "node": ">= 0.8" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/streamx": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.1.tgz", + "integrity": "sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==", + "dependencies": { + "fast-fifo": "^1.1.0", + "queue-tick": "^1.0.1" + } + }, "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==", + "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==", "dependencies": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" } }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } }, "node_modules/string-width": { "version": "4.2.3", @@ -2441,6 +9972,118 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, + "node_modules/superagent": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", + "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.1.2", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=6.4.0 <13 || >=14" + } + }, + "node_modules/superagent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/superagent/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/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/superagent/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/supertest": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.3.tgz", + "integrity": "sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==", + "dependencies": { + "methods": "^1.1.2", + "superagent": "^8.0.5" + }, + "engines": { + "node": ">=6.4.0" + } + }, "node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -2456,6 +10099,94 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "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==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swagger-jsdoc": { + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", + "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", + "dependencies": { + "commander": "6.2.0", + "doctrine": "3.0.0", + "glob": "7.1.6", + "lodash.mergewith": "^4.6.2", + "swagger-parser": "^10.0.3", + "yaml": "2.0.0-1" + }, + "bin": { + "swagger-jsdoc": "bin/swagger-jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/swagger-jsdoc/node_modules/commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/swagger-jsdoc/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", + "dependencies": { + "@apidevtools/swagger-parser": "10.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/swagger-ui-dist": { + "version": "5.9.1", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.9.1.tgz", + "integrity": "sha512-5zAx+hUwJb9T3EAntc7TqYkV716CMqG6sZpNlAAMOMWkNXRYxGkN8ADIvD55dQZ10LxN90ZM/TQmN7y1gpICnw==" + }, + "node_modules/swagger-ui-express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz", + "integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==", + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, "node_modules/tar": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", @@ -2472,6 +10203,26 @@ "node": ">=10" } }, + "node_modules/tar-fs": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", + "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", + "dependencies": { + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + } + }, + "node_modules/tar-stream": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.6.tgz", + "integrity": "sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, "node_modules/tar/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -2483,6 +10234,25 @@ "node": ">=10" } }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -2502,6 +10272,32 @@ "node": ">=0.8" } }, + "node_modules/throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==", + "optional": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2549,6 +10345,19 @@ "node": "*" } }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "optional": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -2598,19 +10407,125 @@ "source-map": "~0.1.7" }, "bin": { - "uglifyjs": "bin/uglifyjs" + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "devOptional": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" }, - "engines": { - "node": ">=0.4.0" + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, + "node_modules/ts-node/node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "devOptional": true, "bin": { - "tree-kill": "cli.js" + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" } }, "node_modules/tslib": { @@ -2618,6 +10533,45 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "optional": true + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "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==", + "dev": true, + "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", @@ -2630,6 +10584,12 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "optional": true + }, "node_modules/typeorm": { "version": "0.3.17", "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.17.tgz", @@ -2811,6 +10771,7 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2837,6 +10798,14 @@ "uglify-to-browserify": "~1.0.0" } }, + "node_modules/uglify-js/node_modules/camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/uglify-js/node_modules/cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", @@ -2880,12 +10849,92 @@ "integrity": "sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==", "optional": true }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/unbzip2-stream/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "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==", + "dev": true, + "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.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "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==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -2894,6 +10943,76 @@ "node": ">= 0.8" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "optional": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" + }, + "node_modules/urlpattern-polyfill": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-9.0.0.tgz", + "integrity": "sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==" + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -2919,6 +11038,34 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "devOptional": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", + "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -2927,6 +11074,26 @@ "node": ">= 0.8" } }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "optional": true + }, "node_modules/void-elements": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", @@ -2935,6 +11102,15 @@ "node": ">=0.10.0" } }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -2949,6 +11125,36 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "optional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -2965,6 +11171,51 @@ "node": ">= 0.8.0" } }, + "node_modules/winston": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz", + "integrity": "sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.6.0.tgz", + "integrity": "sha512-wbBA9PbPAHxKiygo7ub7BYRiKxms0tpfU2ljtWzb3SjRjv5yl6Ozuy/TkXf00HTAt+Uylo3gSkNwzc4ME0wiIg==", + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/with": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/with/-/with-4.0.3.tgz", @@ -3014,6 +11265,59 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "8.14.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", + "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", + "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/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -3027,6 +11331,14 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/yaml": { + "version": "2.0.0-1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", + "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", + "engines": { + "node": ">= 6" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -3051,6 +11363,64 @@ "engines": { "node": ">=12" } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/z-schema": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", + "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "commander": "^9.4.1" + } + }, + "node_modules/z-schema/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "optional": true, + "engines": { + "node": "^12.20.0 || >=14" + } } } } diff --git a/package.json b/package.json index 499a763e..ebc4a4d4 100644 --- a/package.json +++ b/package.json @@ -8,29 +8,56 @@ "scripts": { "start": "node ./bin/www", "build-tsc": "tsc -w", - "run-watch": "nodemon ./dist/app.js", - "dev": "concurrently \"npm:build-tsc\" \"npm:run-watch\"" + "run-watch": "nodemon --loader ts-node/esm ./dist/app.js", + "dev": "concurrently \"npm:build-tsc\" \"npm:run-watch\"", + "test": "tsc && jest", + "build": "tsc --project ." }, "dependencies": { + "@aws-sdk/client-cloudwatch": "^3.427.0", + "@aws-sdk/client-ses": "^3.429.0", + "@types/express-fileupload": "^1.4.2", + "aws-sdk": "^2.1476.0", "bcrypt": "^5.1.1", + "cookie-parser": "^1.4.6", "debug": "~2.6.9", "dotenv": "^16.3.1", + "email-validator": "^2.0.4", "express": "^4.18.2", + "express-fileupload": "^1.4.1", + "html-pdf": "^3.0.1", "http-errors": "~1.6.3", "jade": "~1.11.0", "jsonwebtoken": "^9.0.2", "morgan": "^1.10.0", - "mysql": "^2.18.1", + "mysql2": "^3.6.1", + "puppeteer": "^21.3.8", + "supertest": "^6.3.3", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.0", "typeorm": "^0.3.17", - "typescript": "^5.2.2" + "uuid": "^9.0.1", + "winston": "^3.11.0" }, "devDependencies": { + "@babel/preset-env": "^7.22.20", + "@types/aws-lambda": "^8.10.124", "@types/bcrypt": "^5.0.0", - "@types/express": "^4.17.17", + "@types/cookie-parser": "^1.4.5", + "@types/express": "^4.17.20", + "@types/html-pdf": "^3.0.2", + "@types/jest": "^29.5.5", "@types/jsonwebtoken": "^9.0.2", "@types/morgan": "^1.9.6", "@types/node": "^20.5.6", + "@types/swagger-jsdoc": "^6.0.2", + "@types/swagger-ui-express": "^4.1.5", + "@types/uuid": "^9.0.5", "concurrently": "^8.2.1", - "nodemon": "^3.0.1" + "jest": "^29.7.0", + "nodemon": "^3.0.1", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.1", + "typescript": "^5.2.2" } } diff --git a/src/controllers/AWSServices/CloudWatchLogs.ts b/src/controllers/AWSServices/CloudWatchLogs.ts new file mode 100644 index 00000000..5b26f0b2 --- /dev/null +++ b/src/controllers/AWSServices/CloudWatchLogs.ts @@ -0,0 +1,27 @@ +import { configureCloudWatch } from '../../utilities/AWSConfigureCloudWatch.js'; + +const cloudWatchLogs = configureCloudWatch(); + +if (!cloudWatchLogs) { + throw new Error('CloudWatch Logs initialization failed!'); +} + +export const logToCloudWatch = async (logGroupName:string, logStreamName:string, logMessage:string, id:string, name:string) => { + const logEvent = { + message: `${logMessage}\n- User ID: ${id}, User Name: ${name}`, + timestamp: new Date().getTime(), + }; + + const params = { + logGroupName: logGroupName, + logStreamName: logStreamName, + logEvents: [logEvent], + }; + + try { + await cloudWatchLogs.putLogEvents(params).promise(); + console.log('Log event sent successfully'); + } catch (error) { + console.error('Error sending log event:', error); + } +}; \ No newline at end of file diff --git a/src/controllers/AWSServices/LambdaFunction.ts b/src/controllers/AWSServices/LambdaFunction.ts new file mode 100644 index 00000000..a436ffb6 --- /dev/null +++ b/src/controllers/AWSServices/LambdaFunction.ts @@ -0,0 +1,28 @@ +import { configureLambda } from "../../utilities/AWSConfigureLambdaFunction.js"; + +const lambda = await configureLambda(); + +const invokeLambdaFunction = async (functionName: string, eventPayload: Record) => { + const params = { + FunctionName: functionName, + InvocationType: 'RequestResponse', + Payload: JSON.stringify(eventPayload), + }; + try { + const data = await lambda.invoke(params).promise(); + + if (data.Payload && typeof data.Payload === 'string') { + const response = JSON.parse(data.Payload); + return response; + } else { + throw new Error('Invalid Lambda response format'); + } + } catch (error) { + console.error(error); + throw error; + } +}; + +export{ + invokeLambdaFunction +} \ No newline at end of file diff --git a/src/controllers/AWSServices/S3.ts b/src/controllers/AWSServices/S3.ts new file mode 100644 index 00000000..e5133039 --- /dev/null +++ b/src/controllers/AWSServices/S3.ts @@ -0,0 +1,88 @@ +import { UploadedFile } from "express-fileupload"; +import baseLogger from "../../../logger.js"; +import { VoluntaryWork } from "../../db/entities/VoluntaryWork.js"; +import { configureS3Bucket } from "../../utilities/AWSConfigureS3.js"; + +const S3 = await configureS3Bucket(); + +const putImages = async (id: number, uploadedFiles: UploadedFile[], organizationName: string) => { + try { + + let voluntaryWork = await VoluntaryWork.findOne({ where: { id } }); + if (voluntaryWork) { + + const imageUrls = []; + for (const file of uploadedFiles) { + const uploadParams = { + Bucket: process.env.AWS_BUCKET_NAME || '', + Body: Buffer.from(file.data), + Key: `${organizationName}/${voluntaryWork.name}/${Date.now().toString()}.png`, + ACL: 'public-read', + }; + + const data = await S3.upload(uploadParams).promise(); + imageUrls.push(data.Location); + } + + voluntaryWork.images.push(...imageUrls); + await voluntaryWork.save(); + } + } catch (err) { + baseLogger.error(err); + throw ", when trying to add Image"; + } +} + +const putCertificateTemplate = async (organizationName: string, uploadedFiles: UploadedFile[]) => { + try { + for (const file of uploadedFiles) { + const uploadParams = { + Bucket: process.env.AWS_CERTIFICATES_BUCKET_NAME || '', + Body: Buffer.from(file.data), + Key: `templates/${organizationName}/certificate_template.html`, + ACL: 'public-read', + }; + await S3.upload(uploadParams).promise(); + } + } catch (err) { + baseLogger.error(err); + throw err; + } +} + +const deleteFromS3 = async (key: string, type: string) => { + try { + const deleteParams = { + Bucket: (type === "image" ? process.env.AWS_BUCKET_NAME : process.env.AWS_CERTIFICATES_BUCKET_NAME) || '', + Key: key, + }; + await S3.deleteObject(deleteParams).promise(); + return "Image deleted successfully !" + + } catch (err) { + baseLogger.error("Error deleting image from S3:", err); + throw err; + } +} + +const loadFromS3 = async (bucketName: string, pathPrefix: string) => { + try { + const params = { + Bucket: bucketName, + Prefix: pathPrefix, + }; + + const data = await S3.listObjectsV2(params).promise(); + + const objectKeys = data?.Contents?.map((object) => object.Key); + const imageUrls = (objectKeys || []).filter((imageKey) => Boolean(imageKey)) + .map((imageKey) => `https://${bucketName}.s3.amazonaws.com/${imageKey}`); + + return imageUrls; + } catch (err) { + baseLogger.error('Error listing and generating URLs from S3:', err); + throw err; + } +} + +export { putImages, putCertificateTemplate, deleteFromS3, loadFromS3 } \ No newline at end of file diff --git a/src/controllers/AWSServices/SES.ts b/src/controllers/AWSServices/SES.ts new file mode 100644 index 00000000..caefa34c --- /dev/null +++ b/src/controllers/AWSServices/SES.ts @@ -0,0 +1,50 @@ +import { SendEmailCommand } from "@aws-sdk/client-ses"; +import { SESClient } from "@aws-sdk/client-ses"; +const sesClient = new SESClient({ region: process.env.AWS_REGION }); + +const createSendEmailCommand = (recEmail: string, name: string, subject: string, body: string) => { + return new SendEmailCommand({ + Destination: { + CcAddresses: [], + ToAddresses: [ + recEmail + ], + }, + Message: { + Body: { + Html: { + Charset: "UTF-8", + Data: `Hello, ${name}. ${body}` + }, + Text: { + Charset: "UTF-8", + Data: `...` + }, + }, + Subject: { + Charset: "UTF-8", + Data: subject + }, + }, + Source: "tamimitarteel@gmail.com", + ReplyToAddresses: [] + }); +}; + +const sendEmail = async (email: string, name: string, subject: string, body: string) => { + const sendEmailCommand = createSendEmailCommand( + email, + name, + subject, + body + ); + + try { + return await sesClient.send(sendEmailCommand); + } catch (e) { + console.error("Failed to send email."); + return e; + } +}; + +export { sendEmail }; \ No newline at end of file diff --git a/src/controllers/OrganizationProfile .ts b/src/controllers/OrganizationProfile .ts new file mode 100644 index 00000000..bd1bb402 --- /dev/null +++ b/src/controllers/OrganizationProfile .ts @@ -0,0 +1,122 @@ +import baseLogger from "../../logger.js"; +import { NSOrganizationProfile } from "../../types/organizationProfile.js"; +import { OrganizationAdmin } from "../db/entities/OrganizationAdmin.js"; +import { OrganizationProfile } from "../db/entities/OrganizationProfile.js"; +import createError from 'http-errors'; + +const error = { status: 500, message: 'when trying to manage organization profile' }; + +const createOrganizationProfile = async (payload: NSOrganizationProfile.Item) => { + try { + const newOrganizationProfile = OrganizationProfile.create({ name: payload.name, description: payload.description }); + return newOrganizationProfile.save(); + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const editOrganizationProfile = async (payload: { id: string, name: string, description: string }) => { + try { + let profile = await OrganizationProfile.findOne({ where: { id: payload.id } }); + + if (profile) { + profile = Object.assign(profile, payload); + return profile.save(); + } + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const deleteOrganizationProfile = async (profileId: string) => { + try { + return OrganizationProfile.delete(profileId); + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const searchOrganizationProfile = async (payload: { + page: string, + pageSize: string, + id: string, + name: string, + adminName: string +}) => { + try { + + if (payload.id) { + const organization = await OrganizationProfile.findOne({ where: { id: payload.id } }) + + if (organization) { + return organization; + } else { + error.status = 404; + error.message = "Organization"; + throw error; + } + } + + if (payload.name) { + const organization = await OrganizationProfile.findOne({ where: { name: payload.name } }) + + if (organization) { + return organization; + } else { + error.status = 404; + error.message = "Organization"; + throw error; + } + } + + if (payload.adminName) { + const admin = await OrganizationAdmin.findOne({ where: { name: payload.adminName }, relations: ["orgProfile", "orgProfile.voluntaryWork"] }); + + if (admin) { + return admin.orgProfile; + } else { + error.status = 404; + error.message = "Organization"; + throw error; + } + } + + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const getOrganizationProfile = async (payload: { + page: string, + pageSize: string +}) => { + try { + const page = parseInt(payload.page); + const pageSize = parseInt(payload.pageSize); + + const [orgs, total] = await OrganizationProfile.findAndCount({ + skip: pageSize * (page - 1), + take: pageSize, + order: { + createdAt: 'ASC' + }, + select: ["name", "description", "createdAt"] + }) + + return { + page, + pageSize: orgs.length, + total, + orgs + }; + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +export { getOrganizationProfile, createOrganizationProfile, editOrganizationProfile, deleteOrganizationProfile, searchOrganizationProfile } \ No newline at end of file diff --git a/src/controllers/dataBaseLogger.ts b/src/controllers/dataBaseLogger.ts new file mode 100644 index 00000000..4fcc9ad8 --- /dev/null +++ b/src/controllers/dataBaseLogger.ts @@ -0,0 +1,11 @@ +import { NSLogs } from "../../types/logs.js"; +import { Logs } from "../db/entities/Logs.js"; + +const log = async (payload: NSLogs.Item) => { + + const newLog = Logs.create(payload); + return newLog.save(); + +} + +export { log } \ No newline at end of file diff --git a/src/controllers/index.ts b/src/controllers/index.ts new file mode 100644 index 00000000..21f65b88 --- /dev/null +++ b/src/controllers/index.ts @@ -0,0 +1,47 @@ +const getDate = (date: string): Date => { + let [year, month, day] = date.split('-').map((str) => { return parseInt(str, 10); }); + return new Date(year, month - 1, day, 0, 0, 0, 0); +} + +const isValidPassword = (password: string) => { + const validation = []; + if (password?.length < 10) { + validation.push("The password should be at least 10 characters"); + } + + if (!/[A-Z]/.test(password)) { + validation.push("The password should contains at least one uppercase letter"); + } + + if (!/[a-z]/.test(password)) { + validation.push("The password should contains at least one lowercase letter"); + } + + if (!/[0-9]/.test(password)) { + validation.push("The password should contains at least one digit (number)"); + } + + if (!/[!@#$%^&*()_+{}\[\]:;<>,.?~\\-]/.test(password)) { + validation.push("The password should contains at least one special character"); + } + return validation; +}; + +const isValidDate = (date: string) => { + const datePattern = /^\d{4}-(0?[1-9]|1[0-2])-(0?[1-9]|[12]\d|3[01])$/; + if (!datePattern.test(date)) { + return false; + } + + const [year, month, day] = date.split('-').map(Number); + const daysInMonth: { [key: number]: number } = { + 1: 31, 2: 28, 3: 31, 4: 30, 5: 31, 6: 30, 7: 31, 8: 31, 9: 30, 10: 31, 11: 30, 12: 31, + }; + + if (month === 2 && ((year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0))) { + daysInMonth[2] = 29; + } + + return day <= daysInMonth[month]; +} +export { getDate, isValidPassword, isValidDate }; \ No newline at end of file diff --git a/src/controllers/organizationAdmin.ts b/src/controllers/organizationAdmin.ts new file mode 100644 index 00000000..2896717b --- /dev/null +++ b/src/controllers/organizationAdmin.ts @@ -0,0 +1,216 @@ +import { NSOrganizationAdmin } from "../../types/organizationAdmin.js"; +import { OrganizationAdmin } from "../db/entities/OrganizationAdmin.js"; +import { OrganizationProfile } from "../db/entities/OrganizationProfile.js"; +import bcrypt from 'bcrypt'; +import createError from 'http-errors'; +import { Role } from "../db/entities/Role.js"; +import { Not } from "typeorm"; +import baseLogger from "../../logger.js"; +import { sendEmail } from "./AWSServices/SES.js"; +import jwt from 'jsonwebtoken'; + +const error = { status: 500, message: 'when trying to manage organization admin' }; + +const createOrganizationAdmin = async (payload: NSOrganizationAdmin.Item) => { + try { + const newOrganizationAdmin = OrganizationAdmin.create(payload); + const organization = await OrganizationProfile.findOne({ + where: { id: payload.organizationId }, + }); + + const role = await Role.findOne({ where: { name: "admin" } }); + if (role) { + newOrganizationAdmin.roles = role; + } + + if (organization) { + newOrganizationAdmin.orgProfile = organization; + return newOrganizationAdmin.save(); + } else { + error.status = 404; + error.message = "Organization"; + throw error; + } + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const getOrganizationAdmins = async (payload: { + page: string, + pageSize: string, + id: string, + name: string, + email: string, + organizationName: string +}) => { + const page = parseInt(payload.page); + const pageSize = parseInt(payload.pageSize); + + try { + if (payload.id) { + const admin = await OrganizationAdmin.findOne({ + where: { id: payload.id, name: Not("root") }, + select: ["name", "email", "createdAt"] + }) + if (admin) { + return admin; + } else { + error.status = 404; + error.message = "Admin"; + throw error; + } + } + if (payload.name) { + const admin = await OrganizationAdmin.findOne({ + where: { name: payload.name === 'root' ? "" : payload.name }, + select: ["name", "email", "createdAt"] + }) + if (admin) { + return admin; + } else { + error.status = 404; + error.message = "Admin"; + throw error; + } + } + if (payload.email) { + const admin = await OrganizationAdmin.findOne({ + where: { email: payload.email, name: Not("root") }, + select: ["name", "email", "createdAt"] + }) + if (admin) { + return admin; + } else { + error.status = 404; + error.message = "Admin"; + throw error; + } + } + if (payload.organizationName) { + + const organization = await OrganizationProfile.findOne({ where: { name: payload.organizationName } }); + if (organization) { + const admin = await OrganizationAdmin.findOne({ where: { orgProfile: { id: organization.id } } }); + return { name: admin?.name, createdAt: admin?.createdAt, email: admin?.email }; + } else { + error.status = 404; + error.message = "Organization"; + throw error; + } + } + + const [admins, total] = await OrganizationAdmin.findAndCount({ + skip: pageSize * (page - 1), + take: pageSize, + order: { + createdAt: 'ASC' + }, + where: { + name: Not("root") + }, + select: ["name", "email", "createdAt"] + }) + + return { + page, + pageSize: admins.length, + total, + admins + }; + } catch (err) { + baseLogger.error(err) + throw createError(error.status, error.message); + } +} + +const deleteOrganizationAdmin = async (adminId: string) => { + try { + return OrganizationAdmin.delete(adminId); + } catch (err) { + baseLogger.error(err); + error.status = 500; + error.message = "when trying to delete the admin"; + throw createError(error.status, error.message); + } +} + +const editOrganizationAdmin = async (payload: { id: string, name: string, email: string, organizationName: string }) => { + try { + const admin = await OrganizationAdmin.findOne({ where: { id: payload.id } }); + if (admin) { + if (payload.name) + admin.name = payload.name; + + if (payload.email) + admin.email = payload.email; + + if (payload.organizationName) { + + const profile = await OrganizationProfile.findOne({ where: { name: payload.organizationName } }); + if (profile) { + admin.orgProfile = profile; + } + } + return admin.save(); + + } else { + error.status = 404; + error.message = "Organization"; + throw error; + } + } catch (err) { + baseLogger.error(err) + throw createError(error.status, error.message); + } +} + +const forgetPassword = async (id: string, email: string) => { + const organizationAdmin = await OrganizationAdmin.findOne({ where: { id, email } }); + if (!organizationAdmin) throw "OrganizationAdmin Not exists" + + const secret = process.env.SECRET_KEY + organizationAdmin.password; + const payload = { email, id } + + const token = jwt.sign(payload, secret, { expiresIn: '15m' }); + + const link = `http://localhost:3000/organizationAdmin/reset-password/${id}/${token}` + return sendEmail(email, organizationAdmin.name, "Reset the password", `Use this one time link ${link}`) +} + +const verifyToken = async (id: string, token: string) => { + const organizationAdmin = await OrganizationAdmin.findOne({ where: { id } }); + if (!organizationAdmin) { + throw "OrganizationAdmin not found"; + } + + const secret = process.env.SECRET_KEY + organizationAdmin.password; + + try { + const payload = jwt.verify(token, secret); + } catch (err) { + baseLogger.error(err); + throw "Invalid or expired token"; + } +} + +const resetPassword = async (id: string, token: string, password: string) => { + try { + await verifyToken(id, token); + const organizationAdmin = await OrganizationAdmin.findOne({ where: { id } }); + if (organizationAdmin) { + if (password) { + const hashedPassword = await bcrypt.hash(password, 10); + organizationAdmin.password = hashedPassword; + await organizationAdmin.save(); + return "Password updated successfully!!" + } + } + } catch (err) { + baseLogger.error(err); + throw err; + } +} + +export { forgetPassword, resetPassword, verifyToken, createOrganizationAdmin, deleteOrganizationAdmin, editOrganizationAdmin, getOrganizationAdmins } \ No newline at end of file diff --git a/src/controllers/permission.ts b/src/controllers/permission.ts new file mode 100644 index 00000000..a32219f7 --- /dev/null +++ b/src/controllers/permission.ts @@ -0,0 +1,82 @@ +import baseLogger from "../../logger.js"; +import { NSPermission } from "../../types/permission.js"; +import { Permission } from "../db/entities/Permission.js" +import createError from 'http-errors'; + +const error = { status: 500, message: 'when trying to manage permission' }; + +const createPermission = async (payload: NSPermission.Item) => { + try { + const newPermission = Permission.create(payload) + return newPermission.save(); + } + catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const deletePermission = async (permissionId: number) => { + try { + return Permission.delete(permissionId); + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const editPermission = async (payload: { name: string, id: number }) => { + try { + + const permission = await Permission.findOne({ where: { id: payload.id } }); + + if (permission) { + permission.name = payload.name; + return permission.save(); + } + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const getPermissions = async (payload: { + page: string, + pageSize: string, + id: number, + name: string +}) => { + try { + + const page = parseInt(payload.page); + const pageSize = parseInt(payload.pageSize); + + if (payload.id) { + return Permission.findOne({ where: { id: payload.id } }) + } + + if (payload.name) { + return Permission.findOne({ where: { name: payload.name } }) + } + + const [permissions, total] = await Permission.findAndCount({ + skip: pageSize * (page - 1), + take: pageSize, + order: { + createdAt: 'ASC' + } + }) + + return { + page, + pageSize: permissions.length, + total, + permissions + }; + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +export { createPermission, deletePermission, editPermission, getPermissions } \ No newline at end of file diff --git a/src/controllers/role.ts b/src/controllers/role.ts new file mode 100644 index 00000000..c6738df7 --- /dev/null +++ b/src/controllers/role.ts @@ -0,0 +1,87 @@ +import { In } from "typeorm"; +import { NSRole } from "../../types/role.js"; +import { Permission } from "../db/entities/Permission.js"; +import { Role } from "../db/entities/Role.js"; +import createError from 'http-errors'; +import baseLogger from "../../logger.js"; + +const error = { status: 500, message: 'when trying to manage role' }; + +const createRole = async (payload: NSRole.Item) => { + try { + const newRole = Role.create(payload); + const permissions = await Permission.find({ + where: { id: In(payload.permissionsId) }, + }); + + newRole.permissions = permissions + return newRole.save(); + } + catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const deleteRole = async (roleId: number) => { + try { + return Role.delete(roleId); + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const editRole = async (payload: { name: NSRole.Type, id: number }) => { + try { + + const role = await Role.findOne({ where: { id: payload.id } }); + if (role) { + role.name = payload.name; + return role.save(); + } + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const getRoles = async (payload: { + page: string, + pageSize: string, + id: number, + name: NSRole.Type +}) => { + try { + const page = parseInt(payload.page); + const pageSize = parseInt(payload.pageSize); + + if (payload.id) { + return Role.findOne({ where: { id: payload.id } }) + } + + if (payload.name) { + return Role.findOne({ where: { name: payload.name } }) + } + + const [roles, total] = await Role.findAndCount({ + skip: pageSize * (page - 1), + take: pageSize, + order: { + createdAt: 'ASC' + } + }) + + return { + page, + pageSize: roles.length, + total, + roles + }; + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +export { createRole, editRole, getRoles, deleteRole } \ No newline at end of file diff --git a/src/controllers/voluntaryWork.ts b/src/controllers/voluntaryWork.ts new file mode 100644 index 00000000..50ce8631 --- /dev/null +++ b/src/controllers/voluntaryWork.ts @@ -0,0 +1,924 @@ +import { DeepPartial, In, LessThan, LessThanOrEqual, MoreThan, MoreThanOrEqual } from "typeorm"; +import { NSVoluntaryWork } from "../../types/voluntaryWork.js"; +import { SkillTag } from "../db/entities/SkillTag.js"; +import { VoluntaryWork } from "../db/entities/VoluntaryWork.js"; +import { getDate, isValidDate } from "./index.js"; +import { Volunteer } from "../db/entities/Volunteer.js"; +import createError from 'http-errors'; +import baseLogger from "../../logger.js"; +import { invokeLambdaFunction } from "./AWSServices/LambdaFunction.js"; +import { sendEmail } from "./AWSServices/SES.js"; +import { OrganizationProfile } from "../db/entities/OrganizationProfile.js"; +import { searchOrganizationProfile } from "./OrganizationProfile .js"; +import { OrganizationAdmin } from "../db/entities/OrganizationAdmin.js"; + +const error = { status: 500, message: 'when trying to manage voluntary work' }; + +const createVoluntaryWork = async (payload: NSVoluntaryWork.Item) => { + try { + let payloadDate = { ...payload, startedDate: getDate(payload.startedDate), finishedDate: getDate(payload.finishedDate) }; + + let newVoluntaryWork = VoluntaryWork.create(payloadDate as DeepPartial); + const skillTags = await SkillTag.find({ + where: { id: In(payload.skillTagIds) }, + }); + const organizationAdmin = await OrganizationAdmin.findOne({ where: { id: payload.creatorId } }); + const organization = await searchOrganizationProfile({ page: '', pageSize: '', id: "", name: "", adminName: organizationAdmin?.name || "" }) + organization?.voluntaryWork.push(newVoluntaryWork); + await organization?.save(); + + newVoluntaryWork.skillTags = skillTags; + newVoluntaryWork.feedback = []; + newVoluntaryWork.rating = []; + newVoluntaryWork.images = []; + newVoluntaryWork.volunteerProfiles = []; + return newVoluntaryWork.save(); + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const deleteVoluntaryWork = async (voluntaryWorkId: number) => { + try { + await VoluntaryWork.delete(voluntaryWorkId); + return "Voluntary work entry deleted successfully!" + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const editVoluntaryWork = async (payload: NSVoluntaryWork.Edit) => { + try { + + const id = Number(payload.id) || 0; + let voluntaryWork = await VoluntaryWork.findOne({ where: { id } }); + + if (voluntaryWork) { + voluntaryWork.name = payload.name || voluntaryWork.name; + voluntaryWork.description = payload.description || voluntaryWork.description; + voluntaryWork.location = payload.location || voluntaryWork.location; + voluntaryWork.capacity = payload.capacity || voluntaryWork.capacity; + voluntaryWork.days = payload.days || voluntaryWork.days; + voluntaryWork.images = payload.images || voluntaryWork.images; + voluntaryWork.time = payload.time || voluntaryWork.time; + voluntaryWork.status = payload.status || voluntaryWork.status; + + if (payload.skillTagIds) { + const skillTags = await SkillTag.find({ + where: { id: In(payload.skillTagIds) }, + }); + voluntaryWork.skillTags = skillTags; + } + if (payload.startedDate) { + voluntaryWork.startedDate = getDate(payload.startedDate); + } + if (payload.finishedDate) { + voluntaryWork.finishedDate = getDate(payload.finishedDate); + } + + return voluntaryWork.save(); + } + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const getVoluntaryWork = (payload: { id: number }) => { + try { + return VoluntaryWork.findOne({ where: { id: payload.id } }) + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const getVoluntaryWorks = async (payload: NSVoluntaryWork.GetVoluntaryWorks) => { + try { + + const page = parseInt(payload.page); + const pageSize = parseInt(payload.pageSize); + const conditions: Record = {}; + + if (payload.id) { + conditions["id"] = payload.id; + } + if (payload.name) { + conditions["name"] = payload.name; + } + if (payload.time?.length > 0) { + conditions["time"] = In(payload.time); + } + if (payload.location) { + conditions["location"] = payload.location; + } + if (payload.avgRating) { + conditions["avgRating"] = payload.avgRating; + } + if (payload.status) { + conditions["status"] = payload.status; + } + if (payload.days?.length > 0) { + conditions["days"] = In(payload.days); + } + if (payload.skills?.length > 0) { + conditions["skillTags"] = In(payload.skills); + } + if (payload.startedDate) { + conditions["startedDate"] = payload.startedDate; + } + if (payload.finishedDate) { + conditions["finishedDate"] = payload.finishedDate; + } + if (payload.capacity) { + conditions["capacity"] = payload.capacity; + } + if (payload.creatorId) { + conditions["creatorId"] = payload.creatorId; + } + + if (payload.startedAfter) { + if (!isValidDate(payload.startedAfter)) throw "Invalid date!" + const startedAfterDate = getDate(payload.startedAfter); + conditions["startedDate"] = MoreThan(startedAfterDate); + } + + if (payload.startedBefore) { + if (!isValidDate(payload.startedBefore)) throw "Invalid date!" + const startedBeforeDate = getDate(payload.startedBefore); + conditions["startedDate"] = LessThan(startedBeforeDate); + } + + if (payload.finishedAfter) { + if (!isValidDate(payload.finishedAfter)) throw "Invalid date!" + const finishedAfterDate = getDate(payload.finishedAfter); + conditions["finishedDate"] = MoreThan(finishedAfterDate); + } + + if (payload.finishedBefore) { + if (!isValidDate(payload.finishedBefore)) throw "Invalid date!" + const finishedBeforeDate = getDate(payload.finishedBefore); + conditions["finishedDate"] = LessThan(finishedBeforeDate); + } + + if (payload.avgRatingMore) { + conditions["avgRating"] = MoreThanOrEqual(payload.avgRatingMore); + } + + if (payload.avgRatingLess) { + conditions["avgRating"] = LessThanOrEqual(payload.avgRatingLess); + } + + const [voluntaryWorks, total] = await VoluntaryWork.findAndCount({ + where: conditions, + skip: pageSize * (page - 1), + take: pageSize, + order: { + createdAt: 'ASC' + }, + relations: ['skillTags', 'volunteerProfiles'] + }); + + const processedVW = await Promise.all(voluntaryWorks.map(async vw => { + const volunteers = []; + for (const vp of vw.volunteerProfiles) { + const v = await Volunteer.findOne({ where: { volunteerProfile: { id: vp.id } } }); + if (v) { + volunteers.push({ name: v.name }); + } + } + return { + name: vw.name, + description: vw.description, + days: vw.days, + time: vw.time, + location: vw.location, + startedDate: vw.startedDate, + finishedDate: vw.finishedDate, + status: vw.status, + images: vw.images, + avgRating: vw.avgRating, + feedback: vw.feedback, + capacity: vw.capacity, + skillTags: vw.skillTags.map(st => { return { name: st.name } }), + rating: vw.rating, + volunteers, + volunteerNumbers: volunteers.length, + creatorId: vw.creatorId, + createdAt: vw.createdAt, + }; + })); + + if (processedVW.length == 0) { + error.status = 404; + error.message = "voluntary work"; + throw error; + } + + return { + page, + pageSize: voluntaryWorks.length, + total, + voluntaryWorks: processedVW + }; + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const putRating = async (id: number, rating: number, volunteerName: string) => { + try { + let voluntaryWork = await VoluntaryWork.findOne({ where: { id } }); + if (voluntaryWork) { + const existingRating = voluntaryWork.rating.find(item => item.volunteerName === volunteerName); + if (existingRating) { + existingRating.rating = rating; + } else { + voluntaryWork.rating.push({ volunteerName, rating }); + } + + await voluntaryWork.save(); + voluntaryWork.avgRating = await calculateAvgRating(id) || 0; + await voluntaryWork.save(); + } else { + error.status = 404; + error.message = "voluntary work"; + throw error; + } + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + + +const putFeedback = async (id: number, feedbackText: string, volunteerName: string) => { + try { + let voluntaryWork = await VoluntaryWork.findOne({ where: { id } }); + if (voluntaryWork) { + const existingFeedback = voluntaryWork.feedback.find(item => item.volunteerName === volunteerName); + if (existingFeedback) { + existingFeedback.feedback = feedbackText; + } else { + voluntaryWork.feedback.push({ volunteerName, feedback: feedbackText }); + } + await voluntaryWork.save(); + } else { + error.status = 404; + error.message = "voluntary work"; + throw error; + } + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + + +const registerByVolunteer = async (workId: number, volunteerProfile: Volunteer["volunteerProfile"]) => { + try { + + const voluntaryWork = await VoluntaryWork.findOne({ where: { id: workId }, relations: ["skillTags"] }); + if (!voluntaryWork) { + error.status = 404; + error.message = "voluntary work"; + throw error; + } + + + let skillsMatching = false; + if (voluntaryWork.isSkillsRequired) { + skillsMatching = (voluntaryWork.skillTags?.every(skillTag => volunteerProfile.skillTags.some(workSkill => workSkill.id === skillTag.id))) + } else { + skillsMatching = (voluntaryWork.skillTags?.some(skillTag => volunteerProfile.skillTags.some(workSkill => workSkill.id === skillTag.id))) + } + + if ( + volunteerProfile.availableLocation !== voluntaryWork.location || !skillsMatching || + !(volunteerProfile.availableDays?.length > 0 && volunteerProfile.availableDays?.every(day => voluntaryWork.days.includes(day))) || + !(volunteerProfile.availableTime?.length > 0 && volunteerProfile.availableTime?.every(time => voluntaryWork.time.includes(time))) + + ) { + error.status = 406; + error.message = "Volunteer's profile information does not align with the VoluntaryWork information"; + throw error; + } + + if (voluntaryWork.volunteerProfiles?.length >= voluntaryWork.capacity) { + + error.status = 406; + error.message = "VoluntaryWork is already at full capacity"; + throw error; + } + + if (voluntaryWork.volunteerProfiles) { + voluntaryWork.volunteerProfiles.push(volunteerProfile); + } else { + voluntaryWork.volunteerProfiles = [volunteerProfile]; + } + + if (volunteerProfile.voluntaryWorks) { + volunteerProfile.voluntaryWorks.push(voluntaryWork); + } else { + volunteerProfile.voluntaryWorks = [voluntaryWork]; + } + + await voluntaryWork.save(); + await volunteerProfile.save() + + return "Registration successful!"; + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); // when trying to register by Volunteer + } +} + +const registerByOrganizationAdmin = async (workId: number, volunteerId: string) => { + try { + + const voluntaryWork = await VoluntaryWork.findOne({ where: { id: workId } }); + const volunteer = await Volunteer.findOne({ + where: { id: volunteerId }, + relations: ["roles", "roles.permissions", "volunteerProfile", "volunteerProfile.voluntaryWorks"] + }); + + if (!voluntaryWork) { + error.status = 404; + error.message = "voluntary work"; + throw error; + } + if (!volunteer) { + error.status = 404; + error.message = "volunteer"; + throw error; + } + + if (voluntaryWork.volunteerProfiles) { + voluntaryWork.volunteerProfiles.push(volunteer.volunteerProfile); + } else { + voluntaryWork.volunteerProfiles = [volunteer.volunteerProfile]; + } + + if (volunteer.volunteerProfile.voluntaryWorks) { + volunteer.volunteerProfile.voluntaryWorks.push(voluntaryWork); + } else { + volunteer.volunteerProfile.voluntaryWorks = [voluntaryWork]; + } + + await voluntaryWork.save(); + await volunteer.volunteerProfile.save(); + + return "Registration successful!"; + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); // when trying to register by organization admin + } +} + +const deregisterVoluntaryWork = async (workId: number, volunteerId: string) => { + try { + const voluntaryWork = await VoluntaryWork.findOne({ where: { id: workId }, relations: ["volunteerProfiles"] }); + const volunteer = await Volunteer.findOne({ where: { id: volunteerId }, relations: ["volunteerProfile", "volunteerProfile.voluntaryWorks"] }); + + if (!voluntaryWork) { + error.status = 404; + error.message = "voluntary work"; + throw error; + } + + if (!volunteer) { + error.status = 404; + error.message = "volunteer"; + throw error; + } + + const index = voluntaryWork.volunteerProfiles.findIndex(profile => profile.id === volunteer.volunteerProfile.id); + if (index !== -1) { + voluntaryWork.volunteerProfiles.splice(index, 1); + + const workIndex = volunteer.volunteerProfile.voluntaryWorks.findIndex(work => work.id === workId); + if (workIndex !== -1) { + volunteer.volunteerProfile.voluntaryWorks.splice(workIndex, 1); + } + await Promise.all([voluntaryWork.save(), volunteer.volunteerProfile.save()]); + + return "Deregistration successful!"; + } else { + error.status = 406; + error.message = "Volunteer is not registered for this voluntary work"; + throw error; + } + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); // Error when trying to deregister voluntary work + } +} + +const generateCertificate = async (voluntaryWorkId: number, organizationName: string, date: string) => { + const voluntaryWork = await VoluntaryWork.findOne({ + where: { id: voluntaryWorkId }, + relations: ["volunteerProfiles", "volunteerProfiles.volunteer"] + }); + + if (!voluntaryWork) { + error.status = 404; + error.message = `Voluntary work with id ${voluntaryWorkId}`; + throw error; + } + + const volunteerData = voluntaryWork.volunteerProfiles.map(({ volunteer }) => ({ name: volunteer.name, email: volunteer.email })); + for (const volunteer of volunteerData) { + + const payload = { + volunteerName: volunteer.name, + date, + voluntaryWorkName: voluntaryWork.name, + organizationName, + volunteerEmail: volunteer.email + } + + invokeLambdaFunction("generateCertificate", payload); + } +} + +const getImages = async (voluntaryWorkId: number) => { + const voluntaryWork = await VoluntaryWork.findOne({ + where: { id: voluntaryWorkId } + }); + + return voluntaryWork?.images; +} + +const getVoluntaryWorksForVolunteer = async (volunteerId: string) => { + try { + const volunteer = await Volunteer.findOne({ + where: { id: volunteerId }, + relations: ["volunteerProfile", "volunteerProfile.voluntaryWorks"] + }); + + if (!volunteer) { + error.status = 404; + error.message = "volunteer"; + throw error; + } + return volunteer.volunteerProfile.voluntaryWorks; + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +}; + +const volunteerReminder = async (id: number) => { + try { + + let voluntaryWork = await VoluntaryWork.findOne({ where: { id }, relations: ["volunteerProfiles", "volunteerProfiles.volunteer"] }); + if (!voluntaryWork) { + error.status = 404; + error.message = `Voluntary work with id ${id}`; + throw error; + } + + const volunteerData = voluntaryWork.volunteerProfiles?.map((volunteer) => ({ name: volunteer.volunteer.name, email: volunteer.volunteer.email })); + + for (const volunteer of volunteerData) { + sendEmail( + volunteer.email, + volunteer.name, + 'Reminder to rate and feedback Voluntary Work!', + `You have successfully finished ${voluntaryWork?.name}!\nWe encourage you to tell us your opinion and thoughts about our voluntary work, you can rate and create feedback for it!`) + } + + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const getRecommendation = async (payload: NSVoluntaryWork.Recommendation) => { + try { + + const page = parseInt(payload.page); + const pageSize = parseInt(payload.pageSize); + const conditions: Record = {}; + + if (payload.time?.length > 0) { + conditions["time"] = In(payload.time); + } + if (payload.location) { + conditions["location"] = payload.location; + } + if (payload.status) { + conditions["status"] = payload.status; + } + if (payload.days?.length > 0) { + console.log(7); + conditions["days"] = In(payload.days); + } + if (payload.skillTags?.length > 0) { + conditions["skillTags"] = { id: payload.skillTags }; + } + + const [voluntaryWorks, total] = await VoluntaryWork.findAndCount({ + where: conditions, + skip: pageSize * (page - 1), + take: pageSize, + order: { + createdAt: 'ASC' + }, + relations: ['skillTags', 'volunteerProfiles'] + }); + + const processedVW = await Promise.all(voluntaryWorks.map(async vw => { + const volunteers = []; + for (const vp of vw.volunteerProfiles) { + const v = await Volunteer.findOne({ where: { volunteerProfile: { id: vp.id } } }); + if (v) { + volunteers.push({ name: v.name }); + } + } + return { + name: vw.name, + description: vw.description, + days: vw.days, + time: vw.time, + location: vw.location, + startedDate: vw.startedDate, + finishedDate: vw.finishedDate, + status: vw.status, + capacity: vw.capacity, + skillTags: vw.skillTags.map(st => { return { name: st.name } }), + volunteers, + volunteerNumbers: volunteers.length, + createdAt: vw.createdAt + }; + })); + + return { + page, + pageSize: voluntaryWorks.length, + total, + voluntaryWorks: processedVW + }; + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const deleteImage = async (voluntaryWorkId: number, imageName: string) => { + try { + const voluntaryWork = await VoluntaryWork.findOne({ where: { id: voluntaryWorkId } }); + console.log(imageName); + + if (voluntaryWork) { + const imagesToDelete = voluntaryWork.images.filter((img) => img.endsWith(imageName)); + console.log(imagesToDelete); + + if (imagesToDelete.length > 0) { + for (const imageUrl of imagesToDelete) { + const imageIndex = voluntaryWork.images.findIndex((img) => img === imageUrl); + voluntaryWork.images.splice(imageIndex, 1); + } + + await voluntaryWork.save(); + } + }; + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); // Error when trying to delete an image + } +} + +const calculateAvgRating = async (voluntaryWorkId: number) => { + const voluntaryWork = await VoluntaryWork.findOne({ where: { id: voluntaryWorkId } }); + if (voluntaryWork) { + const avgRating = voluntaryWork.rating.reduce((acc, item) => { return (acc + item.rating) }, 0) / voluntaryWork.rating.length; + return parseFloat(avgRating.toFixed(1)); + } +} + +const getFeedbackAndRating = async (id: number) => { + const voluntaryWork = await VoluntaryWork.findOne({ where: { id } }); + if (voluntaryWork) { + const feedback = voluntaryWork.feedback; + const rating = voluntaryWork.rating; + const result: any = []; + + rating.forEach(item => { + const volunteerFeedback = feedback.find(f => f.volunteerName === item.volunteerName); + result.push({ + volunteerName: item.volunteerName, + rating: item.rating, + feedback: volunteerFeedback ? volunteerFeedback.feedback : '' + }); + }); + + feedback.forEach(item => { + if (!rating.some(ratingItem => ratingItem.volunteerName === item.volunteerName)) { + result.push({ + volunteerName: item.volunteerName, + rating: '', + feedback: item.feedback + }); + } + }); + + const avgRating = voluntaryWork.avgRating; + return { avgRating, data: result }; + } +} + +const deleteRating = async (id: number, volunteerName: string) => { + try { + let voluntaryWork = await VoluntaryWork.findOne({ where: { id } }); + if (voluntaryWork) { + const existingRatingIndex = voluntaryWork.rating.findIndex(item => item.volunteerName === volunteerName); + if (existingRatingIndex !== -1) { + voluntaryWork.rating.splice(existingRatingIndex, 1); + await voluntaryWork.save(); + voluntaryWork.avgRating = await calculateAvgRating(id) || 0; + await voluntaryWork.save(); + } else { + error.status = 404; + error.message = 'Rating for the volunteer'; + throw error; + } + } else { + error.status = 404; + error.message = 'Voluntary work'; + throw error; + } + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +}; + +const deleteFeedback = async (id: number, volunteerName: string) => { + try { + let voluntaryWork = await VoluntaryWork.findOne({ where: { id } }); + if (voluntaryWork) { + const existingFeedbackIndex = voluntaryWork.feedback.findIndex(item => item.volunteerName === volunteerName); + if (existingFeedbackIndex !== -1) { + voluntaryWork.feedback.splice(existingFeedbackIndex, 1); + await voluntaryWork.save(); + } else { + error.status = 404; + error.message = 'Feedback'; + throw error; + } + } else { + error.status = 404; + error.message = 'Voluntary work'; + throw error; + } + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +}; + +const getAnalysis = async () => { + const voluntaryWorks = await VoluntaryWork.find(); + + const avgRating: Record = { + '0-1': 0, '1-2': 0, '2-3': 0, '3-4': 0, '4-5': 0, + }; + + const status: Record = { + 'Pending': 0, + 'In Progress': 0, + 'Finished': 0, + 'Canceled': 0, + }; + + const location: Record = {}; + const capacity: Record = {}; + const startedDates: Record = { + 'Last Week': 0, + 'Last Month': 0, + 'Last Year': 0, + }; + + const finishedDates: Record = { + 'Last Week': 0, + 'Last Month': 0, + 'Last Year': 0, + }; + + const oneWeekAgo = new Date(); + oneWeekAgo.setDate(oneWeekAgo.getDate() - 7); + + const oneMonthAgo = new Date(); + oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1); + + const oneYearAgo = new Date(); + oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1); + + voluntaryWorks.forEach(work => { + const range = Math.floor(work.avgRating); + if (range >= 0 && range <= 4) { + avgRating[`${range}-${range + 1}`]++; + } + + status[work.status]++; + + if (location[work.location]) { + location[work.location]++; + } else { + location[work.location] = 1; + } + + if (capacity[work.capacity]) { + capacity[work.capacity]++; + } else { + capacity[work.capacity] = 1; + } + + const startedDate = new Date(work.startedDate); + if (startedDate >= oneWeekAgo) { + startedDates['Last Week']++; + } else if (startedDate >= oneMonthAgo) { + startedDates['Last Month']++; + } else if (startedDate >= oneYearAgo) { + startedDates['Last Year']++; + } + + if (work.finishedDate) { + const finishedDate = new Date(work.finishedDate); + if (finishedDate >= oneWeekAgo) { + finishedDates['Last Week']++; + } else if (finishedDate >= oneMonthAgo) { + finishedDates['Last Month']++; + } else if (finishedDate >= oneYearAgo) { + finishedDates['Last Year']++; + } + } + }); + + return { + voluntaryWorkNumbers: voluntaryWorks.length, + avgRating, + status, + location, + capacity, + startedDates, + finishedDates + }; +} + +const getOrganizationAnalysis = async (organizationId: string) => { + try { + + const organization = await OrganizationProfile.findOne({ where: { id: organizationId }, relations: ["voluntaryWork"] }); + const voluntaryWorks = organization?.voluntaryWork; + + const avgRating: Record = { + '0-1': 0, '1-2': 0, '2-3': 0, '3-4': 0, '4-5': 0, + }; + + const status: Record = { + 'Pending': 0, + 'In Progress': 0, + 'Finished': 0, + 'Canceled': 0, + }; + + const location: Record = {}; + const capacity: Record = {}; + const startedDates: Record = { + 'Last Week': 0, + 'Last Month': 0, + 'Last Year': 0, + }; + + const finishedDates: Record = { + 'Last Week': 0, + 'Last Month': 0, + 'Last Year': 0, + }; + + const oneWeekAgo = new Date(); + oneWeekAgo.setDate(oneWeekAgo.getDate() - 7); + + const oneMonthAgo = new Date(); + oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1); + + const oneYearAgo = new Date(); + oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1); + + voluntaryWorks?.forEach(work => { + const range = Math.floor(work.avgRating); + if (range >= 0 && range <= 4) { + avgRating[`${range}-${range + 1}`]++; + } + + status[work.status]++; + + if (location[work.location]) { + location[work.location]++; + } else { + location[work.location] = 1; + } + + if (capacity[work.capacity]) { + capacity[work.capacity]++; + } else { + capacity[work.capacity] = 1; + } + + const startedDate = new Date(work.startedDate); + if (startedDate >= oneWeekAgo) { + startedDates['Last Week']++; + } else if (startedDate >= oneMonthAgo) { + startedDates['Last Month']++; + } else if (startedDate >= oneYearAgo) { + startedDates['Last Year']++; + } + + if (work.finishedDate) { + const finishedDate = new Date(work.finishedDate); + if (finishedDate >= oneWeekAgo) { + finishedDates['Last Week']++; + } else if (finishedDate >= oneMonthAgo) { + finishedDates['Last Month']++; + } else if (finishedDate >= oneYearAgo) { + finishedDates['Last Year']++; + } + } + }); + + return { + voluntaryWorkNumbers: voluntaryWorks?.length, + avgRating, + status, + location, + capacity, + startedDates, + finishedDates + }; + + } catch (err) { + baseLogger.error(err); + throw createError(error.status, 'when trying to manage organization analysis'); + } +} + +const findSmallestSufficientTeam = async (voluntaryWorkId: number) => { + const voluntaryWork = await VoluntaryWork.findOne({ where: { id: voluntaryWorkId }, relations: ["skillTags"] }); + + const requiredSkills: string[] = []; + voluntaryWork?.skillTags.forEach((skillTag) => { + requiredSkills.push(skillTag.name); + }); + + const volunteers = await Volunteer.find({ relations: ['volunteerProfile', 'volunteerProfile.skillTags'] }); + const volunteersWithSkills = volunteers.filter((volunteer) => { + return requiredSkills.every((requiredSkill) => + volunteer.volunteerProfile.skillTags.some((skillTag) => skillTag.name === requiredSkill) + ); + }); + + const selectedVolunteers: Volunteer[] = []; + for (const skill of requiredSkills) { + const matchingVolunteer = volunteersWithSkills.find((volunteer) => + volunteer.volunteerProfile.skillTags.some((volunteerSkill) => volunteerSkill.name === skill) + ); + if (matchingVolunteer) { + selectedVolunteers.push(matchingVolunteer); + const index = volunteersWithSkills.indexOf(matchingVolunteer); + volunteersWithSkills.splice(index, 1); + } + } + + const smallestSufficientTeam = selectedVolunteers.map((volunteer) => ({ + id: volunteer.id, + name: volunteer.name, + email: volunteer.email, + })); + + return { smallestSufficientTeamNumber: selectedVolunteers.length, smallestSufficientTeam }; +} + +const sendingEmails = async (name: string) => { + const volunteers = await Volunteer.find(); + for (const volunteer of volunteers) { + sendEmail( + volunteer.email, + volunteer.name, + 'New Voluntary Work !', + `We are pleased to inform you about our new volunteer work entitled ${name}. We are happy for you to join us!`) + } +} + +export { + getVoluntaryWorks, deleteVoluntaryWork, getFeedbackAndRating, sendingEmails, + generateCertificate, getImages, getVoluntaryWorksForVolunteer, getAnalysis, + registerByVolunteer, createVoluntaryWork, getOrganizationAnalysis, + deregisterVoluntaryWork, registerByOrganizationAdmin, findSmallestSufficientTeam, + putFeedback, editVoluntaryWork, putRating, deleteImage, deleteRating, + volunteerReminder, getRecommendation, getVoluntaryWork, deleteFeedback, +} diff --git a/src/controllers/volunteer.ts b/src/controllers/volunteer.ts new file mode 100644 index 00000000..25e8caf8 --- /dev/null +++ b/src/controllers/volunteer.ts @@ -0,0 +1,282 @@ +import { NSVolunteer } from "../../types/volunteer.js"; +import dataSource from "../db/dataSource.js"; +import { Volunteer } from "../db/entities/Volunteer.js"; +import { VolunteerProfile } from "../db/entities/VolunteerProfile.js"; +import { OrganizationAdmin } from "../db/entities/OrganizationAdmin.js"; +import jwt from 'jsonwebtoken'; +import bcrypt from 'bcrypt'; +import { SkillTag } from "../db/entities/SkillTag.js"; +import { In, Like } from "typeorm"; +import createError from 'http-errors'; +import { Role } from "../db/entities/Role.js"; +import baseLogger from "../../logger.js"; +import { sendEmail } from "./AWSServices/SES.js"; + +const error = { status: 500, message: 'when trying to manage volunteer' }; + +const createVolunteer = async (payload: NSVolunteer.Item) => { + try { + + return dataSource.manager.transaction(async (transaction) => { + const existingSkillTags = await SkillTag.find({ + where: { name: In(payload.skills) }, + }); + + const newSkillTags = await Promise.all( + payload.skills.map(async (skillName) => { + return existingSkillTags.find((tag) => tag.name === skillName) || + (await transaction.save(SkillTag.create({ name: skillName }))); + }) + ); + + const profile = VolunteerProfile.create({ + availableTime: payload.availableTime, + availableLocation: payload.availableLocation, + availableDays: payload.availableDays, + skillTags: newSkillTags + }); + await transaction.save(profile); + + const newVolunteer = Volunteer.create(payload); + newVolunteer.volunteerProfile = profile; + + const role = await Role.findOne({ where: { name: payload.type } }); + if (role) { + newVolunteer.roles = [role]; + } + + await transaction.save(newVolunteer); + profile.volunteer = newVolunteer; + await transaction.save(profile); + return newVolunteer + }); + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +}; + +const deleteVolunteer = async (volunteerId: string) => { + try { + return Volunteer.delete(volunteerId); + } catch (err) { + baseLogger.error(err); + throw createError({ status: 404, message: "Volunteer" }); + } +} + +const editVolunteer = async (payload: { name: string, id: string, email: string }) => { + try { + const volunteer = await Volunteer.findOne({ where: { id: payload.id } }); + if (volunteer) { + if (payload.name) + volunteer.name = payload.name; + + if (payload.email) + volunteer.email = payload.email; + + return volunteer.save(); + } + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const login = async (email: string, name: string, id: string) => { + try { + const volunteer = await Volunteer.findOne({ + where: { email, name, id }, + relations: ["roles", "roles.permissions"], + }); + + const organizationAdmin = await OrganizationAdmin.findOne({ + where: { email, name, id }, + relations: ["roles", "roles.permissions"], + }); + + if (volunteer) { + const token = jwt.sign( + { email, name, id }, + process.env.SECRET_KEY || '', + { + expiresIn: "1d" + } + ); + return { token, volunteer, organizationAdmin: null }; + } else if (organizationAdmin) { + const token = jwt.sign( + { email, name, id }, + process.env.SECRET_KEY || '', + { + expiresIn: "1d" + } + ); + return { token, organizationAdmin, volunteer: null }; + } else { + error.status = 400; + error.message = 'Invalid email or name or id !'; + throw error; + } + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } + +} + +const getVolunteers = async (payload: NSVolunteer.Item & { page: string; pageSize: string }) => { + try { + const page = parseInt(payload.page); + const pageSize = parseInt(payload.pageSize); + const conditions: Record = {}; + + if (payload.id) { + conditions["id"] = payload.id; + } + if (payload.name) { + conditions["name"] = Like(`%${payload.name}%`); + } + if (payload.email) { + conditions["email"] = payload.email; + } + if (payload.availableLocation) { + conditions["volunteerProfile"] = { availableLocation: Like(`%${payload.availableLocation}%`) }; + } + if (payload.type) { + conditions["type"] = payload.type; + } + const [volunteers, total] = await Volunteer.findAndCount({ + where: conditions, + order: { + createdAt: 'ASC', + }, + relations: [ + "volunteerProfile.skillTags", + "volunteerProfile" + ], + select: [ + "name", + "email", + "type", + "volunteerProfile" + ], + }); + + const processedVolunteers = volunteers.map((volunteer) => { + return { + name: volunteer.name, + email: volunteer.email, + type: volunteer.type, + createdAt: volunteer.createdAt, + volunteerProfile: { + availableTime: volunteer.volunteerProfile?.availableTime, + availableDays: volunteer.volunteerProfile?.availableDays, + availableLocation: volunteer.volunteerProfile?.availableLocation, + dateOfBirth: volunteer.volunteerProfile?.dateOfBirth, + roles: volunteer.roles, + skillTags: volunteer.volunteerProfile?.skillTags?.map((skillTag) => { + return { name: skillTag.name }; + }), + }, + }; + }); + + const filteredVolunteers = processedVolunteers.filter((volunteer) => { + if (payload.skills.length > 0) { + const hasMatchingSkill = volunteer.volunteerProfile.skillTags.some((skillTag) => payload.skills.includes(skillTag.name)); + return hasMatchingSkill; + } + return true; + }); + + const finalFilteredVolunteers = filteredVolunteers.filter((volunteer) => { + if (payload.availableTime && payload.availableTime.length > 0) { + if (!volunteer.volunteerProfile || !volunteer.volunteerProfile.availableTime) { + return false; + } + return payload.availableTime.every(time => volunteer.volunteerProfile.availableTime.includes(time)); + } + + if (payload.availableDays && payload.availableDays.length > 0) { + if (!volunteer.volunteerProfile || !volunteer.volunteerProfile.availableDays) { + return false; + } + return payload.availableDays.every(day => volunteer.volunteerProfile.availableDays.includes(day)); + } + + return true; + }); + + if (finalFilteredVolunteers.length == 0) { + error.status = 404; + error.message = "Volunteer"; + throw error; + } + + const startIndex = (page - 1) * pageSize; + const endIndex = startIndex + pageSize; + const paginatedVolunteers = finalFilteredVolunteers.slice(startIndex, endIndex); + + return { + page, + pageSize: paginatedVolunteers.length, + total: finalFilteredVolunteers.length, + volunteers: paginatedVolunteers, + }; + } catch (err) { + baseLogger.error(err); + throw createError(error.status, error.message); + } +} + +const forgetPassword = async (id: string, email: string) => { + const volunteer = await Volunteer.findOne({ where: { id, email } }); + if (!volunteer) throw "Volunteer Not exists" + + const secret = process.env.SECRET_KEY + volunteer.password; + const payload = { email, id } + + const token = jwt.sign(payload, secret, { expiresIn: '15m' }); + + const link = `http://localhost:3000/volunteer/reset-password/${id}/${token}` + return sendEmail(email, volunteer.name, "Reset the password", `Use this one time link ${link}`) + +} + +const verifyToken = async (id: string, token: string) => { + const volunteer = await Volunteer.findOne({ where: { id } }); + if (!volunteer) { + throw "Volunteer not found"; + } + + const secret = process.env.SECRET_KEY + volunteer.password; + + try { + const payload = jwt.verify(token, secret); + } catch (err) { + baseLogger.error(err); + throw "Invalid or expired token"; + } +} + +const resetPassword = async (id: string, token: string, password: string) => { + try { + await verifyToken(id, token); + const volunteer = await Volunteer.findOne({ where: { id } }); + if (volunteer) { + if (password) { + const hashedPassword = await bcrypt.hash(password, 10); + volunteer.password = hashedPassword; + await volunteer.save(); + return "Password updated successfully!!" + } + } + } catch (err) { + baseLogger.error(err); + throw err; + } +} + +export { resetPassword, verifyToken, forgetPassword, getVolunteers, login, createVolunteer, deleteVolunteer, editVolunteer } + diff --git a/src/db/dataSource.ts b/src/db/dataSource.ts index f107c65e..7f23fbd6 100644 --- a/src/db/dataSource.ts +++ b/src/db/dataSource.ts @@ -1,18 +1,34 @@ import { DataSource } from "typeorm"; +import { OrganizationAdmin } from "./entities/OrganizationAdmin.js"; +import { OrganizationProfile } from "./entities/OrganizationProfile.js"; +import { Permission } from "./entities/Permission.js"; +import { Role } from "./entities/Role.js"; +import { SkillTag } from "./entities/SkillTag.js"; +import { VoluntaryWork } from "./entities/VoluntaryWork.js"; +import { Volunteer } from "./entities/Volunteer.js"; +import { VolunteerProfile } from "./entities/VolunteerProfile.js"; +import { Logs } from "./entities/Logs.js"; const dataSource = new DataSource({ - type: 'mysql', - host: process.env.DB_HOST, - port: Number(process.env.DB_PORT), - username: process.env.DB_USERNAME, - password: process.env.DB_PASSWORD, - database: process.env.DB_NAME, - entities: [ - - ], - migrations: ['./**/migration/*.ts'], - synchronize: true, - logging: false + + type: 'mysql', + host: process.env.DB_HOST, + port: Number(process.env.DB_PORT), + username: process.env.DB_USERNAME, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + entities: [OrganizationAdmin, OrganizationProfile, Permission, + Role, SkillTag, VoluntaryWork, Volunteer, VolunteerProfile, Logs], + migrations: ['./**/migration/*.ts'], + synchronize: true, + logging: false }); -export default dataSource; \ No newline at end of file +export const initDB = async () => + await dataSource.initialize().then(() => { + console.log("Connected to DB!"); + }).catch(err => { + console.log('Failed to connect to DB: ' + err) + }); + +export default dataSource; diff --git a/src/db/entities/Logs.ts b/src/db/entities/Logs.ts new file mode 100644 index 00000000..82a6bc3b --- /dev/null +++ b/src/db/entities/Logs.ts @@ -0,0 +1,40 @@ +import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn } from "typeorm"; + +@Entity() +export class Logs extends BaseEntity { + @PrimaryGeneratedColumn('increment') + id: number; + + @Column({ + nullable:true, + }) + userId: string; + + @Column({ + nullable:true + }) + userName: string; + + @Column({ + nullable:true + }) + userType: string; + + @Column({ + type: 'enum', + enum: ['success', 'failed'], + nullable: true + }) + type: 'success' | 'failed'; + + @Column({ + nullable:true + }) + request: string + + @CreateDateColumn({ + type: 'timestamp', + default: () => "CURRENT_TIMESTAMP(6)" + }) + createdAt: Date; +} \ No newline at end of file diff --git a/src/db/entities/OrganizationAdmin.ts b/src/db/entities/OrganizationAdmin.ts new file mode 100644 index 00000000..1cfdc913 --- /dev/null +++ b/src/db/entities/OrganizationAdmin.ts @@ -0,0 +1,45 @@ +import { BaseEntity, BeforeInsert, Column, CreateDateColumn, Entity, JoinColumn, ManyToOne, OneToOne, PrimaryGeneratedColumn } from "typeorm"; +import bcrypt from 'bcrypt'; +import { Role } from "./Role.js"; +import { OrganizationProfile } from "./OrganizationProfile.js"; + +@Entity() +export class OrganizationAdmin extends BaseEntity { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column({ length: 255, nullable: false }) + name: string; + + @Column({ nullable: false, unique:true }) + email: string; + + @BeforeInsert() + async hashPassword() { + if (this.password) { + this.password = await bcrypt.hash(this.password, 10) + } + } + @Column({ nullable: false }) + password: string; + + @Column({ + type: 'enum', + enum: ['male', 'female'], + nullable: true + }) + gender: 'male' | 'female' + + @OneToOne(() => OrganizationProfile, {cascade: true, onDelete:"SET NULL", onUpdate:"CASCADE"}) + @JoinColumn() + orgProfile: OrganizationProfile; + + @ManyToOne(() => Role, role => role.orgAdmins) + roles: Role; + + @CreateDateColumn({ + type: 'timestamp', + default: () => "CURRENT_TIMESTAMP(6)" + }) + createdAt: Date; +} \ No newline at end of file diff --git a/src/db/entities/OrganizationProfile.ts b/src/db/entities/OrganizationProfile.ts new file mode 100644 index 00000000..2b47e217 --- /dev/null +++ b/src/db/entities/OrganizationProfile.ts @@ -0,0 +1,23 @@ +import { BaseEntity, Column, CreateDateColumn, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { VoluntaryWork } from "./VoluntaryWork.js"; + +@Entity() +export class OrganizationProfile extends BaseEntity { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column({ length: 255, nullable: false, unique:true }) + name: string; + + @Column({nullable: false}) + description: string; + + @OneToMany(() => VoluntaryWork, voluntaryWork => voluntaryWork.orgProfiles, {cascade:true, onDelete:"SET NULL", onUpdate:"CASCADE"}) + voluntaryWork: VoluntaryWork[]; + + @CreateDateColumn({ + type: 'timestamp', + default: () => "CURRENT_TIMESTAMP(6)" + }) + createdAt: Date; +} \ No newline at end of file diff --git a/src/db/entities/Permission.ts b/src/db/entities/Permission.ts new file mode 100644 index 00000000..b0177c43 --- /dev/null +++ b/src/db/entities/Permission.ts @@ -0,0 +1,21 @@ +import { BaseEntity, Column, CreateDateColumn, Entity, JoinTable, ManyToMany, PrimaryGeneratedColumn } from "typeorm"; +import { Role } from "./Role.js"; + +@Entity() +export class Permission extends BaseEntity { + @PrimaryGeneratedColumn('increment') + id: number; + + @Column({ unique: true }) + name: string; + + @ManyToMany(() => Role) + @JoinTable() + roles: Role[]; + + @CreateDateColumn({ + type: 'timestamp', + default: () => "CURRENT_TIMESTAMP(6)" + }) + createdAt: Date; +} \ No newline at end of file diff --git a/src/db/entities/Role.ts b/src/db/entities/Role.ts new file mode 100644 index 00000000..39945699 --- /dev/null +++ b/src/db/entities/Role.ts @@ -0,0 +1,35 @@ +import { BaseEntity, Column, CreateDateColumn, Entity, JoinTable, ManyToMany, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { Permission } from "./Permission.js"; +import { Volunteer } from "./Volunteer.js"; +import { OrganizationAdmin } from "./OrganizationAdmin.js"; + +@Entity() +export class Role extends BaseEntity { + @PrimaryGeneratedColumn('increment') + id: number; + + @Column({ + type: 'enum', + enum: ['root', 'admin', 'volunteer', 'premium'], + default: 'volunteer', + unique:true + }) + name: 'root' | 'admin' | 'volunteer' | 'premium'; + + @ManyToMany(() => Volunteer) + @JoinTable() + volunteers: Volunteer[]; + + @ManyToMany(() => Permission, {cascade:true, onUpdate:"CASCADE"}) + @JoinTable() + permissions: Permission[]; + + @OneToMany(() => OrganizationAdmin, organizationAdmin => organizationAdmin.roles) + orgAdmins: OrganizationAdmin[]; + + @CreateDateColumn({ + type: 'timestamp', + default: () => "CURRENT_TIMESTAMP(6)" + }) + createdAt: Date; +} \ No newline at end of file diff --git a/src/db/entities/SkillTag.ts b/src/db/entities/SkillTag.ts new file mode 100644 index 00000000..66f8d9b9 --- /dev/null +++ b/src/db/entities/SkillTag.ts @@ -0,0 +1,26 @@ +import { BaseEntity, Column, CreateDateColumn, Entity, JoinTable, ManyToMany, PrimaryGeneratedColumn } from "typeorm"; +import { VolunteerProfile } from "./VolunteerProfile.js"; +import { VoluntaryWork } from "./VoluntaryWork.js"; + +@Entity() +export class SkillTag extends BaseEntity { + @PrimaryGeneratedColumn('increment') + id: number; + + @Column({ unique: true }) + name: string; + + @ManyToMany(() => VolunteerProfile) + @JoinTable() + volunteerProfiles: VolunteerProfile[]; + + @ManyToMany(() => VoluntaryWork) + @JoinTable() + voluntaryWorks: VoluntaryWork[]; + + @CreateDateColumn({ + type: 'timestamp', + default: () => "CURRENT_TIMESTAMP(6)" + }) + createdAt: Date; +} \ No newline at end of file diff --git a/src/db/entities/VoluntaryWork.ts b/src/db/entities/VoluntaryWork.ts new file mode 100644 index 00000000..7ab7d7c1 --- /dev/null +++ b/src/db/entities/VoluntaryWork.ts @@ -0,0 +1,84 @@ +import { BaseEntity, Column, CreateDateColumn, Entity, JoinTable, ManyToMany, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; +import { SkillTag } from "./SkillTag.js"; +import { VolunteerProfile } from "./VolunteerProfile.js"; +import { OrganizationProfile } from "./OrganizationProfile.js"; +import { NSVolunteer } from "../../../types/volunteer.js"; +import { NSVoluntaryWork } from "../../../types/voluntaryWork.js"; + +@Entity() +export class VoluntaryWork extends BaseEntity { + @PrimaryGeneratedColumn('increment') + id: number; + + @Column({ unique: true, nullable: false }) + name: string; + + @Column({ nullable: false }) + description: string; + + @Column({ + type: 'json', + nullable: false + }) + days: NSVolunteer.AvailableDays[]; + + @Column({ + type: 'json', + nullable: false + }) + time: NSVolunteer.AvailableTime[]; + + @Column({ nullable: false }) + location: string; + + @Column({ nullable: false, type: "timestamp" }) + startedDate: Date; + + @Column({ nullable: true, type: "timestamp" }) + finishedDate: Date; + + @Column({ + type: 'enum', + enum: ['Pending', 'In Progress', 'Finished', 'Canceled'], + nullable: false + }) + status: 'Pending' | 'In Progress' | 'Finished' | 'Canceled'; + + @Column({ type: 'json', nullable: true }) + images: string[]; + + @Column({ nullable: true, default: 0.0, type: 'float' }) + avgRating: number; + + @Column({ type: 'json', nullable: true }) + feedback: NSVoluntaryWork.Feedback[]; + + @Column({ type: 'json', nullable: true }) + rating: NSVoluntaryWork.Rating[]; + + @Column({ nullable: false }) + capacity: number; + + @Column({ nullable: false }) + isSkillsRequired: boolean + + @Column({ nullable: false }) + creatorId: string; + + @ManyToMany(() => SkillTag) + @JoinTable() + skillTags: SkillTag[]; + + @ManyToMany(() => VolunteerProfile) + @JoinTable() + volunteerProfiles: VolunteerProfile[]; + + @ManyToOne(() => OrganizationProfile, organizationProfile => organizationProfile.voluntaryWork) + orgProfiles: OrganizationProfile; + + @CreateDateColumn({ + type: 'timestamp', + default: () => "CURRENT_TIMESTAMP(6)" + }) + createdAt: Date; +} \ No newline at end of file diff --git a/src/db/entities/Volunteer.ts b/src/db/entities/Volunteer.ts new file mode 100644 index 00000000..aa7493bb --- /dev/null +++ b/src/db/entities/Volunteer.ts @@ -0,0 +1,48 @@ +import { BaseEntity, BeforeInsert, Column, CreateDateColumn, Entity, JoinColumn, JoinTable, ManyToMany, OneToOne, PrimaryGeneratedColumn } from "typeorm"; +import bcrypt from 'bcrypt'; +import { Role } from "./Role.js"; +import { VolunteerProfile } from "./VolunteerProfile.js"; +import { NSVolunteer } from "../../../types/volunteer.js"; + +@Entity() +export class Volunteer extends BaseEntity implements NSVolunteer.IVolunteer { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column({ length: 255, nullable: false }) + name: string; + + @Column({ nullable: false, unique:true }) + email: string; + + @BeforeInsert() + async hashPassword() { + if (this.password) { + this.password = await bcrypt.hash(this.password, 10) + } + } + @Column({ nullable: false }) + password: string; + + @Column({ + type: 'enum', + enum: ['volunteer', 'premium'], + default: 'volunteer', + nullable: true + }) + type: 'volunteer' | 'premium'; + + @ManyToMany(() => Role) + @JoinTable() + roles: Role[]; + + @OneToOne(() => VolunteerProfile, { cascade: true, onDelete: "SET NULL" }) + @JoinColumn() + volunteerProfile: VolunteerProfile + + @CreateDateColumn({ + type: 'timestamp', + default: () => "CURRENT_TIMESTAMP(6)" + }) + createdAt: Date; +} \ No newline at end of file diff --git a/src/db/entities/VolunteerProfile.ts b/src/db/entities/VolunteerProfile.ts new file mode 100644 index 00000000..422aeaef --- /dev/null +++ b/src/db/entities/VolunteerProfile.ts @@ -0,0 +1,54 @@ +import { BaseEntity, Column, CreateDateColumn, Entity, JoinColumn, JoinTable, ManyToMany, OneToOne, PrimaryGeneratedColumn } from "typeorm"; +import { SkillTag } from "./SkillTag.js"; +import { VoluntaryWork } from "./VoluntaryWork.js"; +import { NSVolunteer } from "../../../types/volunteer.js"; +import { Volunteer } from "./Volunteer.js"; + +@Entity() +export class VolunteerProfile extends BaseEntity { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column({ + type: 'json', + nullable: false + }) + availableTime: NSVolunteer.AvailableTime[]; + + @Column({ + type: 'json', + nullable: false + }) + availableDays: NSVolunteer.AvailableDays[]; + + @Column({ nullable: false }) + availableLocation: string; + + @Column({ nullable: true, type: "timestamp" }) + dateOfBirth: Date; + + @ManyToMany(() => SkillTag) + @JoinTable() + skillTags: SkillTag[]; + + @OneToOne(() => Volunteer, (volunteer) => volunteer.volunteerProfile, { onDelete: 'SET NULL' }) + @JoinColumn() + volunteer: NSVolunteer.IVolunteer; + + @ManyToMany(() => VoluntaryWork) + @JoinTable() + voluntaryWorks: VoluntaryWork[]; + + @Column({ + type: 'enum', + enum: ['male', 'female'], + nullable: true + }) + gender: 'male' | 'female' + + @CreateDateColumn({ + type: 'timestamp', + default: () => "CURRENT_TIMESTAMP(6)" + }) + createdAt: Date; +} \ No newline at end of file diff --git a/src/db/migration/1697004288562-CreatePermissions.ts b/src/db/migration/1697004288562-CreatePermissions.ts new file mode 100644 index 00000000..840cdd17 --- /dev/null +++ b/src/db/migration/1697004288562-CreatePermissions.ts @@ -0,0 +1,82 @@ +import { MigrationInterface, QueryRunner } from "typeorm" + +export class CreatePermissions1697004288562 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + INSERT INTO permission (name, createdAt) + VALUES + ('GET_me', NOW()), + ('GET_volunteers', NOW()), + ('PUT_volunteer', NOW()), + ('DELETE_volunteer', NOW()), + ('GET_organizationAdmins', NOW()), + ('POST_organizationAdmin', NOW()), + ('PUT_organizationAdmin', NOW()), + ('DELETE_organizationAdmin', NOW()), + ('GET_organizationProfiles', NOW()), + ('POST_organizationProfile', NOW()), + ('PUT_organizationProfile', NOW()), + ('DELETE_organizationProfile', NOW()), + ('GET_voluntaryWorks', NOW()), + ('POST_voluntaryWork', NOW()), + ('PUT_voluntaryWork', NOW()), + ('REGISTER_voluntaryWork', NOW()), + ('DEREGISTER_voluntaryWork', NOW()), + ('DELETE_voluntaryWork', NOW()), + ('GET_recommendation', NOW()), + ('GET_analysis', NOW()), + ('PUT_rating', NOW()), + ('PUT_feedback', NOW()), + ('PUT_images', NOW()), + ('GET_permissions', NOW()), + ('POST_permission', NOW()), + ('PUT_permission', NOW()), + ('DELETE_permission', NOW()), + ('GET_roles', NOW()), + ('POST_role', NOW()), + ('PUT_role', NOW()), + ('DELETE_role', NOW()) + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + DELETE FROM permission + WHERE name IN ( + 'GET_me', + 'GET_volunteers', + 'PUT_volunteer', + 'DELETE_volunteer', + 'GET_organizationAdmins', + 'POST_organizationAdmin', + 'PUT_organizationAdmin', + 'DELETE_organizationAdmin', + 'GET_organizationProfiles', + 'POST_organizationProfile', + 'PUT_organizationProfile', + 'DELETE_organizationProfile', + 'GET_voluntaryWorks', + 'POST_voluntaryWork', + 'PUT_voluntaryWork', + 'REGISTER_voluntaryWork', + 'DEREGISTER_voluntaryWork', + 'DELETE_voluntaryWork', + 'GET_recommendation', + 'GET_analysis', + 'PUT_rating', + 'PUT_feedback', + 'PUT_images', + 'GET_permissions', + 'POST_permission', + 'PUT_permission', + 'DELETE_permission', + 'GET_roles', + 'POST_role', + 'PUT_role', + 'DELETE_role' + ) + `); + } + +} diff --git a/src/db/migration/1697005494066-CreateRoles.ts b/src/db/migration/1697005494066-CreateRoles.ts new file mode 100644 index 00000000..565e5dfb --- /dev/null +++ b/src/db/migration/1697005494066-CreateRoles.ts @@ -0,0 +1,132 @@ +import { MigrationInterface, QueryRunner } from "typeorm" + +export class CreateRoles1697005494066 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + INSERT INTO role (name) + VALUES ('root') + `); + + const result = await queryRunner.query(` + SELECT id FROM role WHERE name = 'root' + `); + + const roleId = result[0].id; + const permissionIds = [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + ]; + + for (const permissionId of permissionIds) { + await queryRunner.query(` + INSERT INTO role_permissions_permission (roleId, permissionId) + VALUES (${roleId}, ${permissionId}) + `); + } + + await queryRunner.query(` + INSERT INTO role (name) + VALUES ('admin') +`); + + // Get the ID of the inserted 'admin' role + const adminRoleId = (await queryRunner.query(` + SELECT id FROM role WHERE name = 'admin' +`))[0].id; + + // Insert permissions for the 'admin' role + const adminPermissionIds = [1, 2, 3, 4, 5, 9, 13, 14, 16, 17]; + + for (const permissionId of adminPermissionIds) { + await queryRunner.query(` + INSERT INTO role_permissions_permission (roleId, permissionId) + VALUES (${adminRoleId}, ${permissionId}) + `); + } + + await queryRunner.query(` + INSERT INTO role (name) + VALUES ('premium') +`); + + const premiumRoleId = (await queryRunner.query(` + SELECT id FROM role WHERE name = 'premium' +`))[0].id; + + const premiumPermissionIds = [1, 2, 5, 9, 13, 14, 16, 17, 19, 21, 22]; + + for (const permissionId of premiumPermissionIds) { + await queryRunner.query(` + INSERT INTO role_permissions_permission (roleId, permissionId) + VALUES (${premiumRoleId}, ${permissionId}) + `); + } + + // Insert the 'volunteer' role + await queryRunner.query(` + INSERT INTO role (name) + VALUES ('volunteer') +`); + + // Get the ID of the inserted 'volunteer' role + const volunteerRoleId = (await queryRunner.query(` + SELECT id FROM role WHERE name = 'volunteer' +`))[0].id; + + // Insert permissions for the 'volunteer' role + const volunteerPermissionIds = [1, 2, 5, 9, 13, 16, 17, 19, 21, 22]; + + for (const permissionId of volunteerPermissionIds) { + await queryRunner.query(` + INSERT INTO role_permissions_permission (roleId, permissionId) + VALUES (${volunteerRoleId}, ${permissionId}) + `); + } + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + DELETE FROM role WHERE name = 'root' +`); + + const permissionIdsToDelete = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]; + + for (const permissionId of permissionIdsToDelete) { + await queryRunner.query(` + DELETE FROM role_permissions_permission + WHERE roleId = (SELECT id FROM role WHERE name = 'root') AND permissionId = ${permissionId} + `); + } + await queryRunner.query(` + DELETE FROM role_permissions_permission + WHERE roleId = (SELECT id FROM role WHERE name = 'admin') +`); + + await queryRunner.query(` + DELETE FROM role WHERE name = 'admin' +`); + + // Delete the 'premium' role and its associated permissions + await queryRunner.query(` + DELETE FROM role_permissions_permission + WHERE roleId = (SELECT id FROM role WHERE name = 'premium') +`); + + await queryRunner.query(` + DELETE FROM role WHERE name = 'premium' +`); + + // Delete the 'volunteer' role and its associated permissions + await queryRunner.query(` + DELETE FROM role_permissions_permission + WHERE roleId = (SELECT id FROM role WHERE name = 'volunteer') +`); + + await queryRunner.query(` + DELETE FROM role WHERE name = 'volunteer' +`); + } + +} diff --git a/src/db/migration/1697005554406-RootUser.ts b/src/db/migration/1697005554406-RootUser.ts new file mode 100644 index 00000000..a79bf748 --- /dev/null +++ b/src/db/migration/1697005554406-RootUser.ts @@ -0,0 +1,29 @@ +import { MigrationInterface, QueryRunner } from "typeorm" +import { OrganizationAdmin } from "../entities/OrganizationAdmin.js"; +import { Role } from "../entities/Role.js"; + +export class RootUser1697005554406 implements MigrationInterface { + +public async up(queryRunner: QueryRunner): Promise { + const newOrgAdmin = new OrganizationAdmin(); + newOrgAdmin.name = "root"; + newOrgAdmin.email = ""; + newOrgAdmin.password = "root"; + + const rootRole = await queryRunner.manager.findOne(Role, { where: { name: "root" } }); + + if (rootRole) { + newOrgAdmin.roles = rootRole; + } else { + console.error("The 'root' role does not exist."); + } + await newOrgAdmin.save(); +} +public async down(queryRunner: QueryRunner): Promise { + + const orgAdminToDelete = await queryRunner.manager.findOne(OrganizationAdmin, { where: { name: "root" } }); + if (orgAdminToDelete) { + await orgAdminToDelete.remove(); + } +} +} diff --git a/src/middleware/auth/authenticate.ts b/src/middleware/auth/authenticate.ts new file mode 100644 index 00000000..d5199102 --- /dev/null +++ b/src/middleware/auth/authenticate.ts @@ -0,0 +1,75 @@ +import express from 'express'; +import jwt, { JwtPayload } from 'jsonwebtoken'; +import { OrganizationAdmin } from '../../db/entities/OrganizationAdmin.js'; +import { Volunteer } from '../../db/entities/Volunteer.js'; +import createError from 'http-errors'; +import { NSLogs } from '../../../types/logs.js'; +import { log } from '../../controllers/dataBaseLogger.js'; + +const authenticate = async ( + req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const token = req.cookies['myApp'] || ''; + let tokenIsValid: JwtPayload | null | string; + + try { + tokenIsValid = jwt.verify(token, process.env.SECRET_KEY || ''); + } catch (error) { + tokenIsValid = null; + } + + if (tokenIsValid) { + const decoded = tokenIsValid as JwtPayload; + + const organizationAdmin = await OrganizationAdmin.findOne({ + where: { name: decoded.name, email: decoded.email, id: decoded.id }, + relations: ["roles", "roles.permissions"] + }); + const volunteer = await Volunteer.findOne({ + where: { name: decoded.name, email: decoded.email, id: decoded.id }, + relations: ["roles", "roles.permissions", "volunteerProfile", "volunteerProfile.skillTags","volunteerProfile.voluntaryWorks"] + }); + + if (organizationAdmin) { + res.locals.organizationAdmin = organizationAdmin; + res.cookie('name', res.locals.organizationAdmin.name, { + httpOnly: true, + maxAge: 60 * 24 * 60 * 1000, + sameSite: "lax" // Protect against CSRF attacks + }); + next(); + } else if (volunteer) { + res.locals.volunteer = volunteer; + res.cookie('name', res.locals.volunteer.name, { + httpOnly: true, + maxAge: 60 * 24 * 60 * 1000, + sameSite: "lax" // Protect against CSRF attacks + }); + next(); + } else { + log({ + userId: "", + userName: "", + userType: "" as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Authentication failed' + }).then().catch() + next(createError(401)); + } + } else { + log({ + userId: "", + userName: "", + userType: "" as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Authentication failed' + }).then().catch() + next(createError(401)); + } +} + +export { + authenticate +} diff --git a/src/middleware/auth/authorize.ts b/src/middleware/auth/authorize.ts new file mode 100644 index 00000000..c45bd699 --- /dev/null +++ b/src/middleware/auth/authorize.ts @@ -0,0 +1,212 @@ +import express from 'express'; +import { NSPermission } from '../../../types/permission.js'; +import { OrganizationAdmin } from '../../db/entities/OrganizationAdmin.js'; +import { Volunteer } from '../../db/entities/Volunteer.js'; +import { VoluntaryWork } from '../../db/entities/VoluntaryWork.js'; +import createError from 'http-errors'; +import { log } from '../../controllers/dataBaseLogger.js'; +import { NSLogs } from '../../../types/logs.js'; + +const authorize = (api: string) => { + return async ( + req: express.Request, + res: express.Response, + next: express.NextFunction + ) => { + const permissions: NSPermission.Item[] = []; + + if (res.locals.organizationAdmin) { + const organizationAdmin: OrganizationAdmin = res.locals.organizationAdmin; + permissions.push(...(organizationAdmin.roles.permissions)); + + } else if (res.locals.volunteer) { + const volunteer: Volunteer = res.locals.volunteer; + volunteer.roles.forEach((role) => { + permissions.push(...role.permissions); + }); + } + + if (permissions?.filter(p => p.name === api).length > 0) { + next(); + } else if ((/^PUT_.+/.test(api)) || (/^DELETE_.+/.test(api))) { + if ((/organizationProfile$/.test(api))) { + checkAdmin(req, res, next); + } else if ((/organizationAdmin$/.test(api)) || (/volunteer$/.test(api))) { + checkMe(req, res, next); + } else if ((/voluntaryWork$/.test(api)) || ((/images/.test(api)))) { + checkCreator(req, res, next); + } else { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Authorization failed to ' + api + }).then().catch() + next(createError(401)); + } + } else { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Authorization failed to ' + api + }).then().catch() + next(createError(401)); + } + } +} + +const checkMe = (req: express.Request, res: express.Response, next: express.NextFunction) => { + + const id = req.params.id; + if (res.locals.volunteer) { + if (res.locals.volunteer.id == id) { + next(); + } else { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Authorization failed' + }).then().catch() + next(createError(401)); + } + } else if (res.locals.organizationAdmin) { + if (res.locals.organizationAdmin.id == id) { + next(); + } else { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type) as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Authorization failed' + }).then().catch() + next(createError(401)); + } + } + +} + +const checkAdmin = async (req: express.Request, res: express.Response, next: express.NextFunction) => { + const id = req.params.id; + const admin = await OrganizationAdmin.findOne({ where: { orgProfile: { id } } }); + + if (res.locals.organizationAdmin) { + if (res.locals.organizationAdmin.id == admin?.id) { + next(); + } else { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Authorization failed' + }).then().catch() + next(createError(401)); + } + } else { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type) as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Authorization failed' + }).then().catch() + next(createError(401)); + } +} + +const checkCreator = async (req: express.Request, res: express.Response, next: express.NextFunction) => { + const id = Number(req.params.id); + + let voluntaryWork = await VoluntaryWork.findOne({ where: { id } }); + + if (res.locals.organizationAdmin) { + if (res.locals.organizationAdmin.id == voluntaryWork?.creatorId) { + next(); + } else { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Authorization failed' + }).then().catch() + next(createError(401)); + } + } else if (res.locals.volunteer) { + if (res.locals.volunteer?.id == voluntaryWork?.creatorId) { + next(); + } else { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type) as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Authorization failed' + }).then().catch() + next(createError(401)); + } + } else { + next(createError(401)); + } +} + +const checkParticipation = async (req: express.Request, res: express.Response, next: express.NextFunction) => { + const id = Number(req.params.id); + + if (res.locals.volunteer) { + const volunteer = res.locals.volunteer; + const volunteerProfile = volunteer.volunteerProfile; + + if (volunteerProfile) { + const voluntaryWork = await VoluntaryWork.findOne({ + where: { id }, + relations: ['volunteerProfiles'] + }); + + if (voluntaryWork) { + // Check if volunteerProfile.id exists in the array of volunteerProfiles' ids + const isParticipating = voluntaryWork.volunteerProfiles.some(profile => profile.id === volunteerProfile.id); + + if (isParticipating) { + next(); + } else { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type) as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Authorization failed' + }).then().catch() + next(createError(401)); + } + } else { + next(createError(404, "Voluntary Work")); // Optional: Handle the case when voluntaryWork is not found + } + } else { + next(createError(401)); // Handle the case when volunteerProfile is not defined + } + } else { + log({ + userId: res.locals.organizationAdmin?.id ||res.locals.volunteer?.id, + userName:res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Authorization failed' + }).then().catch() + next(createError(401)); // Handle the case when res.locals.volunteer is not defined + } +}; + +export { + authorize, + checkMe, + checkAdmin, + checkCreator, + checkParticipation +} \ No newline at end of file diff --git a/src/middleware/errorHandler/errorHandler.ts b/src/middleware/errorHandler/errorHandler.ts new file mode 100644 index 00000000..64d851ae --- /dev/null +++ b/src/middleware/errorHandler/errorHandler.ts @@ -0,0 +1,25 @@ +import express from "express" + +const errorHandler = ( + error: any, + req: express.Request, + res: express.Response, + next: express.NextFunction) => { + if (error.status == 404) { + res.status(404).send(error.message + " is NOT found"); + } else if (error.status == 401) { + res.status(401).send("You are unauthorized"); + } else if (error.status == 403) { + res.status(403).send("You don't have the permission"); + } else if (error.status == 400) { + res.status(400).send("Your request is BAD, " + error.message); + } else if (error.status == 406) { + res.status(406).send("Your request is NOT acceptable, " + error.message); + } else { + res.status(500).send('Something went wrong, ' + error.message); + } +} + +export { + errorHandler +} \ No newline at end of file diff --git a/src/middleware/validation/organizationAdmin.ts b/src/middleware/validation/organizationAdmin.ts new file mode 100644 index 00000000..ad1a0593 --- /dev/null +++ b/src/middleware/validation/organizationAdmin.ts @@ -0,0 +1,104 @@ +import express from 'express'; +import * as EmailValidator from 'email-validator'; +import { isValidPassword } from '../../controllers/index.js'; +import { OrganizationAdmin } from '../../db/entities/OrganizationAdmin.js'; +import createError from 'http-errors'; +import { NSLogs } from '../../../types/logs.js'; +import { log } from '../../controllers/dataBaseLogger.js'; + + +const validateOrganizationAdmin = (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const values = ["name", "email", "password", "organizationId"]; + const organizationAdmin = req.body; + const errorList = values.map(key => !organizationAdmin[key] && `${key} is Required!`).filter(Boolean); + + if (!EmailValidator.validate(organizationAdmin.email)) { + errorList.push('Email is not Valid'); + } + + errorList.push(...isValidPassword(organizationAdmin.password)); + + if (errorList.length) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad Organization Admin Request' + }).then().catch() + res.status(400).send(errorList); + } else { + next(); + } +} + +const validateAdminEdited = async (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const organizationAdmin = req.body; + const errorList = []; + + const id = req.params.id.toString(); + const v = await OrganizationAdmin.findOne({ where: { id } }); + if (!v) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad Organization Admin Request' + }).then().catch() + next(createError(404, "Organization admin")); + } + + if (organizationAdmin.email) { + if (!EmailValidator.validate(organizationAdmin.email)) { + errorList.push('Email is not Valid'); + } + } + if (organizationAdmin.password) + errorList.push(...isValidPassword(organizationAdmin.password)); + + if (errorList.length) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad Organization Admin Request' + }).then().catch() + res.status(400).send(errorList); + } else { + next(); + } +} + +const validateAdminId = async (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const id = req.params.id.toString(); + const p = await OrganizationAdmin.findOne({ where: { id } }); + if (!p) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad Organization Admin Request' + }).then().catch() + next(createError(404, "Organization admin")); + } else { + next(); + } +} + +export { + validateOrganizationAdmin, + validateAdminEdited, + validateAdminId +} \ No newline at end of file diff --git a/src/middleware/validation/organizationProfile.ts b/src/middleware/validation/organizationProfile.ts new file mode 100644 index 00000000..97d5c624 --- /dev/null +++ b/src/middleware/validation/organizationProfile.ts @@ -0,0 +1,60 @@ +import express from 'express'; +import { OrganizationProfile } from '../../db/entities/OrganizationProfile.js'; +import createError from 'http-errors'; +import { NSLogs } from '../../../types/logs.js'; +import { log } from '../../controllers/dataBaseLogger.js'; + +const validateOrganizationProfile = (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const values = ["name", "description"]; + const organizationProfile = req.body; + const errorList = values.map(key => !organizationProfile[key] && `${key} is Required!`).filter(Boolean); + + if (errorList.length) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad Organization Profile Request' + }).then(() => { + console.log('logged'); + }).catch(err => { + console.log('NOT logged'); + }) + res.status(400).send(errorList); + } else { + next(); + } +} + +const validateOrgId = async (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const id = req.params.id.toString(); + const v = await OrganizationProfile.findOne({ where: { id } }); + if (!v) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad Organization Profile Request' + }).then(() => { + console.log('logged'); + }).catch(err => { + console.log('NOT logged'); + }) + next(createError(404, "Organization Profile")); + } else { + next(); + } +} + +export { + validateOrganizationProfile, + validateOrgId +} \ No newline at end of file diff --git a/src/middleware/validation/permission.ts b/src/middleware/validation/permission.ts new file mode 100644 index 00000000..9528a918 --- /dev/null +++ b/src/middleware/validation/permission.ts @@ -0,0 +1,60 @@ +import express from 'express'; +import { Permission } from '../../db/entities/Permission.js'; +import createError from 'http-errors'; +import { NSLogs } from '../../../types/logs.js'; +import { log } from '../../controllers/dataBaseLogger.js'; + +const validatePermission = (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const values = ["name"]; + const permission = req.body; + const errorList = values.map(key => !permission[key] && `${key} is Required!`).filter(Boolean); + + if (errorList.length) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad Permission Request' + }).then(() => { + console.log('logged'); + }).catch(err => { + console.log('NOT logged'); + }) + res.status(400).send(errorList); + } else { + next(); + } +} + +const validatePermissionId = async (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const id = Number(req.params.id.toString()); + const p = await Permission.findOne({ where: { id } }); + if (!p) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Invalid Permission id' + }).then(() => { + console.log('logged'); + }).catch(err => { + console.log('NOT logged'); + }) + next(createError(404, "Permission")); + } else { + next(); + } +} + +export { + validatePermission, + validatePermissionId +} \ No newline at end of file diff --git a/src/middleware/validation/role.ts b/src/middleware/validation/role.ts new file mode 100644 index 00000000..c2bf3a9b --- /dev/null +++ b/src/middleware/validation/role.ts @@ -0,0 +1,113 @@ +import express from 'express'; +import { Role } from '../../db/entities/Role.js'; +import createError from 'http-errors'; +import { NSLogs } from '../../../types/logs.js'; +import { log } from '../../controllers/dataBaseLogger.js'; + +const validateRole = (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const values = ['name', "permissionsId"]; + const role = req.body; + const errorList = values.map(key => !role[key] && `${key} is Required!`).filter(Boolean); + + if (!['root', 'admin', 'volunteer', 'premium'].includes(role.name)) { + errorList.push('role name unknown!'); + } + + if (errorList.length) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad Role Request' + }).then(() => { + console.log('logged'); + }).catch(err => { + console.log('NOT logged'); + }) + res.status(400).send(errorList); + } else { + next(); + } +} + +const validateEditedRole = async (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const role = req.body; + const errorList = []; + + const id = Number(req.params.id.toString()); + const r = await Role.findOne({ where: { id } }); + if (!r) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Invalid Role id' + }).then(() => { + console.log('logged'); + }).catch(err => { + console.log('NOT logged'); + }) + next(createError(404, "Role")); + } + + if (role.name) { + if (!['root', 'admin', 'volunteer', 'premium'].includes(role.name)) { + errorList.push('role name unknown!'); + } + } + + if (errorList.length) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad Role Request' + }).then(() => { + console.log('logged'); + }).catch(err => { + console.log('NOT logged'); + }) + res.status(400).send(errorList); + } else { + next(); + } +} +const validateRoleId = async (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const id = Number(req.params.id.toString()); + const p = await Role.findOne({ where: { id } }); + if (!p) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Invalid Role id' + }).then(() => { + console.log('logged'); + }).catch(err => { + console.log('NOT logged'); + }) + next(createError(404, "Role")); + } else { + next(); + } +} + + +export { + validateRole, + validateEditedRole, + validateRoleId +} \ No newline at end of file diff --git a/src/middleware/validation/voluntaryWork.ts b/src/middleware/validation/voluntaryWork.ts new file mode 100644 index 00000000..0cd0d9bc --- /dev/null +++ b/src/middleware/validation/voluntaryWork.ts @@ -0,0 +1,237 @@ +import express from 'express'; +import { NSVoluntaryWork } from '../../../types/voluntaryWork.js'; +import { NSVolunteer } from '../../../types/volunteer.js'; +import { getDate, isValidDate } from '../../controllers/index.js'; +import { VoluntaryWork } from '../../db/entities/VoluntaryWork.js'; +import createError from 'http-errors'; +import { NSLogs } from '../../../types/logs.js'; +import { log } from '../../controllers/dataBaseLogger.js'; +import { logToCloudWatch } from '../../controllers/AWSServices/CloudWatchLogs.js'; + +const validateVoluntaryWork = (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const values = ["name", "description", "location", "time", "status", "days", "startedDate", "finishedDate", "capacity", "skillTagIds"]; + const voluntaryWork = req.body; + const errorList = values.map(key => !voluntaryWork[key] && `${key} is Required!`).filter(Boolean); + + const validStatus = Object.values(NSVoluntaryWork.StatusType).includes(voluntaryWork.status); + if (!validStatus) { + errorList.push("Invalid status !"); + } + + const validTime = voluntaryWork.time.every((time: string) => Object.values(NSVolunteer.AvailableTime).includes(time as NSVolunteer.AvailableTime)); + if (!validTime) { + errorList.push("Invalid time !"); + } + + const validDays = voluntaryWork.days.every((days: string) => Object.values(NSVolunteer.AvailableDays).includes(days as NSVolunteer.AvailableDays)); + if (!validDays) { + errorList.push("Invalid days !"); + } + + if (voluntaryWork.capacity < 1 || voluntaryWork.capacity > 40) { + errorList.push("Invalid capacity !"); + } + if (!isValidDate(voluntaryWork.startedDate) || !isValidDate(voluntaryWork.finishedDate)) { + errorList.push("Invalid date !") + } + if (getDate(voluntaryWork.startedDate) > getDate(voluntaryWork.finishedDate)) { + errorList.push("The started date should be before the finished date !"); + } + + if (errorList.length > 0) { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad Voluntary Work Request' + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Bad Voluntary Work Request', + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + res.status(400).send(errorList); + } else { + next(); + } +} + +const validateEditedVoluntaryWork = async (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const voluntaryWork = req.body; + const errorList = []; + + const id = Number(req.params.id.toString()); + const vw = await VoluntaryWork.findOne({ where: { id } }); + if (!vw) { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Invalid Voluntary Work id' + }).then(() => { + console.log('logged'); + }).catch(err => { + console.log('NOT logged'); + }) + next(createError(404, "Voluntary work")); + } + + if (voluntaryWork.status) { + const validStatus = Object.values(NSVoluntaryWork.StatusType).includes(voluntaryWork.status); + if (!validStatus) { + errorList.push("Invalid status !"); + } + } + + if (voluntaryWork.time) { + const validTime = voluntaryWork.time.every((time: string) => Object.values(NSVolunteer.AvailableTime).includes(time as NSVolunteer.AvailableTime)); + if (!validTime) { + errorList.push("Invalid time !"); + } + } + + if (voluntaryWork.days) { + const validDays = voluntaryWork.days.every((days: string) => Object.values(NSVolunteer.AvailableDays).includes(days as NSVolunteer.AvailableDays)); + if (!validDays) { + errorList.push("Invalid days !"); + } + } + + if (voluntaryWork.capacity) { + if (voluntaryWork.capacity < 1 || voluntaryWork.capacity > 40) { + errorList.push("Invalid capacity !"); + } + } + if (voluntaryWork.startedDate || voluntaryWork.finishedDate) { + if (!isValidDate(voluntaryWork.startedDate) || !isValidDate(voluntaryWork.finishedDate)) { + errorList.push("Invalid date !") + } + } + if (voluntaryWork.startedDate && voluntaryWork.finishedDate) { + if (getDate(voluntaryWork.startedDate) > getDate(voluntaryWork.finishedDate)) { + errorList.push("The started date should be before the finished date !"); + } + } else if (voluntaryWork.startedDate && vw) { + if (getDate(voluntaryWork.startedDate) > vw.finishedDate) { + errorList.push("The started date should be before the finished date !"); + } + } else if (voluntaryWork.finishedDate && vw) { + if (vw.startedDate > getDate(voluntaryWork.finishedDate)) { + errorList.push("The started date should be before the finished date !"); + } + } + + if (errorList.length) { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad Voluntary Work Request' + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Bad Voluntary Work Request', + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + res.status(400).send(errorList); + } else { + next(); + } +} + +const validateVoluntaryWorkId = async (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const id = Number(req.params.id.toString()); + const p = await VoluntaryWork.findOne({ where: { id } }); + if (!p) { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Invalid Voluntary Work id' + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Invalid Voluntary Work id', + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + next(createError(404, "Voluntary work")); + } else { + next(); + } +} + +const validateDeleteFromS3 = async (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const values = ["imageName"]; + const voluntaryWork = req.body; + const errorList = values.map(key => !voluntaryWork[key] && `${key} is Required!`).filter(Boolean); + + if (errorList.length > 0) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad delete image from Voluntary Work Request' + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Bad delete image from Voluntary Work Request', + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + res.status(400).send(errorList); + } else { + next(); + } +} + +const validateRating = (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const values = ["rating"]; + const voluntaryWork = req.body; + const errorList = values.map(key => !voluntaryWork[key] && `${key} is Required!`).filter(Boolean); + + if (req.body.rating < 1 || req.body.rating > 5) { + errorList.push("Rating should be between 1 and 5") + }else{ + next() + } +} + +export { + validateVoluntaryWork, + validateEditedVoluntaryWork, + validateVoluntaryWorkId, + validateDeleteFromS3, + validateRating +} \ No newline at end of file diff --git a/src/middleware/validation/volunteer.ts b/src/middleware/validation/volunteer.ts new file mode 100644 index 00000000..425d5bb8 --- /dev/null +++ b/src/middleware/validation/volunteer.ts @@ -0,0 +1,187 @@ +import express from 'express'; +import * as EmailValidator from 'email-validator'; +import { isValidPassword } from '../../controllers/index.js'; +import { NSVolunteer } from '../../../types/volunteer.js'; +import { Volunteer } from '../../db/entities/Volunteer.js'; +import createError from 'http-errors' +import { NSLogs } from '../../../types/logs.js'; +import { log } from '../../controllers/dataBaseLogger.js'; + + +const validateVolunteer = (req: express.Request, res: express.Response, next: express.NextFunction) => { + const volunteer = req.body; + volunteer.type = "volunteer"; + const errorList: string[] = []; + + const requiredFields = ["name", "email", "password", "availableTime", "availableLocation", "availableDays", "skills"]; + requiredFields.forEach((field) => { + if (!volunteer[field]) { + errorList.push(`${field} is required.`); + } + }); + // const values = ["name", "email", "password", "availableTime", "availableLocation", "availableDays", "skills"]; + // const errorList = values.map(key => !volunteer[key] && `${key} is Required!`).filter(Boolean); + + if (!EmailValidator.validate(volunteer.email)) { + errorList.push('Email is not valid.'); + } + + if (volunteer.type) { + const validType = Object.values(NSVolunteer.TypeVolunteer).includes(volunteer.type); + if (!validType) { + errorList.push("Invalid type!"); + } + } + + const validTime = volunteer.availableTime.every((time: string) => Object.values(NSVolunteer.AvailableTime).includes(time as NSVolunteer.AvailableTime)); + if (!validTime) { + errorList.push("Invalid time!"); + } + + const validDays = volunteer.availableDays.every((days: string) => Object.values(NSVolunteer.AvailableDays).includes(days as NSVolunteer.AvailableDays)); + if (!validDays) { + errorList.push("Invalid days!"); + } + + errorList.push(...isValidPassword(volunteer.password)); + + if (errorList.length) { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad Volunteer Request' + }).then(() => { + console.log('logged'); + }).catch(err => { + console.log('NOT logged'); + }) + res.status(400).send({ errors: errorList }); + } else { + next(); + } +}; + +const validateEditedVolunteer = async (req: express.Request, res: express.Response, next: express.NextFunction) => { + const volunteer = req.body; + const errorList: string[] = []; + + const id = req.params.id.toString(); + const v = await Volunteer.findOne({ where: { id } }); + if (!v) { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Invalid Volunteer id' + }).then(() => { + console.log('logged'); + }).catch(err => { + console.log('NOT logged'); + }) + next(createError(404, "Volunteer")); + } + + if (volunteer.email) { + if (!EmailValidator.validate(volunteer.email)) { + errorList.push('Email is not valid.'); + } + } + + if (volunteer.type) { + const validType = Object.values(NSVolunteer.TypeVolunteer).includes(volunteer.type); + if (!validType) { + errorList.push("Invalid type!"); + } + } + + if (volunteer.availableTime) { + const validTime = volunteer.availableTime.every((time: string) => Object.values(NSVolunteer.AvailableTime).includes(time as NSVolunteer.AvailableTime)); + if (!validTime) { + errorList.push("Invalid time!"); + } + } + + if (volunteer.availableDays) { + const validDays = volunteer.availableDays.every((days: string) => Object.values(NSVolunteer.AvailableDays).includes(days as NSVolunteer.AvailableDays)); + if (!validDays) { + errorList.push("Invalid days!"); + } + } + + if (volunteer.password) { + errorList.push(...isValidPassword(volunteer.password)); + } + + if (errorList.length) { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad Volunteer Request' + }).then(() => { + console.log('logged'); + }).catch(err => { + console.log('NOT logged'); + }) + res.status(400).send({ errors: errorList }); + } else { + next(); + } +}; + +const validateVolunteerId = async (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const id = (req.params.id.toString()); + const p = await Volunteer.findOne({ where: { id } }); + if (!p) { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Invalid Volunteer id' + }).then(() => { + console.log('logged'); + }).catch(err => { + console.log('NOT logged'); + }) + next(createError(404, "Volunteer")); + } else { + next(); + } +} + +const validateLogin = async (req: express.Request, + res: express.Response, + next: express.NextFunction +) => { + const values = ["name", "id", "email"]; + const voluntaryWork = req.body; + const errorList = values.map(key => !voluntaryWork[key] && `${key} is Required!`).filter(Boolean); + + if (errorList.length) { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Bad login Request' + }).then().catch() + res.status(400).send({ errors: errorList }); + } else { + next(); + } +} + +export { + validateVolunteer, + validateEditedVolunteer, + validateVolunteerId, + validateLogin +} \ No newline at end of file diff --git a/src/routes/organizationAdmin.ts b/src/routes/organizationAdmin.ts new file mode 100644 index 00000000..359ac673 --- /dev/null +++ b/src/routes/organizationAdmin.ts @@ -0,0 +1,751 @@ +import express from "express"; +import { createOrganizationAdmin, deleteOrganizationAdmin, editOrganizationAdmin, forgetPassword, getOrganizationAdmins, resetPassword, verifyToken } from "../controllers/organizationAdmin.js"; +import { authorize } from "../middleware/auth/authorize.js"; +import { validateAdminEdited, validateAdminId, validateOrganizationAdmin } from "../middleware/validation/organizationAdmin.js"; +import { log } from "../controllers/dataBaseLogger.js"; +import { NSLogs } from "../../types/logs.js"; +import { logToCloudWatch } from "../controllers/AWSServices/CloudWatchLogs.js"; +import { login } from "../controllers/volunteer.js"; +import { authenticate } from "../middleware/auth/authenticate.js"; +import { validateLogin } from "../middleware/validation/volunteer.js"; + +const router = express.Router(); + +router.post('/signup', authorize("POST_organizationAdmin"), validateOrganizationAdmin, (req, res, next) => { + createOrganizationAdmin(req.body).then(async (data) => { + log({ + userId: data.id, + userName: req.body.name, + userType: 'root' as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Create Organization Admin ' + data.name + }).then().catch() + + logToCloudWatch( + 'success', + 'organization admin', + 'Create Organization Admin ' + data.name, + data.id, + req.body.name + ).then().catch() + const { password, ...dataWithoutPassword } = data; + res.status(201).send({ message: "Organization Admin created successfully!!", dataWithoutPassword }) + }).catch(async err => { + log({ + userId: "", + userName: req.body.name, + userType: 'root' as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Create Organization Admin ' + req.body.name + }).then().catch() + + logToCloudWatch( + 'failed', + 'organization admin', + 'Create Organization Admin ' + req.body.name, + "", + req.body.name + ).then().catch() + + next(err); + }); +}); + +router.post('/login', validateLogin, (req, res, next) => { + const email = req.body.email; + const name = req.body.name; + const id = req.body.id; + login(email, name, id) + .then(data => { + res.cookie('myApp', data.token, { + httpOnly: true, + maxAge: 60 * 24 * 60 * 1000, + sameSite: "lax" // Protect against CSRF attacks + }); + + log({ + userId: id, + userName: name, + userType: (data.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Login ' + (name) + }).then().catch() + + logToCloudWatch( + 'success', + 'organization admin', + 'Login ' + (name), + id, + name + ).then().catch() + + res.status(200).send("You logged in successfully !"); + }) + .catch(err => { + log({ + userId: id, + userName: name, + userType: 'volunteer' as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Login ' + (name) + }).then().catch() + + logToCloudWatch( + 'failed', + 'organization admin', + 'Login ' + name, + id, + name + ).then().catch() + + res.status(401).send(err); + }) +}); + +router.get("/logout", authenticate, (req, res, next) => { + res.cookie("name", '', { + maxAge: -1 + }) + res.cookie("myApp", '', { + maxAge: -1 + }) + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Logout ' + (res.locals.organizationAdmin?.name) + }).then().catch() + + logToCloudWatch( + 'success', + 'volunteer', + 'Logout ' + (res.locals.organizationAdmin?.name), + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.send("You logged out successfully !"); +}) + +router.delete('/:id', authenticate, validateAdminId, authorize("DELETE_organizationAdmin"), async (req, res, next) => { + const id = req.params.id?.toString(); + + deleteOrganizationAdmin(id) + .then(async data => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Delete Organization Admin with id: ' + id + }).then().catch() + + logToCloudWatch( + 'success', + 'organization admin', + 'Delete Organization Admin with id: ' + id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(async err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Delete Organization Admin with id: ' + id + }).then().catch() + + logToCloudWatch( + 'failed', + 'organization admin', + 'Delete Organization Admin with id: ' + id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.put("/:id", authenticate, authorize("PUT_organizationAdmin"), validateAdminEdited, async (req, res, next) => { + editOrganizationAdmin({ ...req.body, id: req.params.id }).then(async () => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Edit Organization Admin with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'organization admin', + 'Edit Organization Admin with id: ' + req.params.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.status(200).send("Organization Admin edited successfully!!") + }).catch(async err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Edit Organization Admin with id: ' + req.params.id + }) + + logToCloudWatch( + 'failed', + 'organization admin', + 'Edit Organization Admin with id: ' + req.params.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.get('/search', authenticate, authorize("GET_organizationAdmins"), async (req, res, next) => { + const payload = { + page: req.query.page?.toString() || '1', + pageSize: req.query.pageSize?.toString() || '10', + id: req.query.id?.toString() || '', + name: req.query.name?.toString() || '', + email: req.query.email?.toString() || '', + organizationName: req.query.organizationName?.toString() || '' + }; + + getOrganizationAdmins(payload) + .then(async data => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Get Organization Admin/s' + }).then().catch() + + logToCloudWatch( + 'success', + 'organization admin', + 'Get Organization Admin/s', + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + res.send(data); + }) + .catch(async err => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Get Organization Admin/s' + }).then().catch() + + logToCloudWatch( + 'failed', + 'organization admin', + 'Get Organization Admin/s', + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + next(err); + }); +}); + +router.get("/forget-password", authenticate, authorize("POST_voluntaryWork"), (req, res, next) => { + forgetPassword(res.locals.organizationAdmin?.id, res.locals.organizationAdmin?.email).then(() => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Forget password organization admin id ' + res.locals.organizationAdmin?.id + }).then().catch() + + logToCloudWatch( + 'success', + 'organization admin', + 'Forget password organization admin id ' + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.send("Password reset link has been sent to your email") + }).catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Forget password organization admin id ' + res.locals.organizationAdmin?.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'organization admin', + 'Forget password organization admin id ' + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }) +}) + +router.get("/reset-password/:id/:token", authenticate, authorize("POST_voluntaryWork"), validateAdminId, async (req, res, next) => { + const { id, token } = req.params; + + try { + await verifyToken(id, token); + res.cookie('reset-password', token, { + httpOnly: true, + maxAge: 15 * 60 * 1000, + sameSite: "lax" + }); + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Validate token to reset password for organization admin id ' + res.locals.organizationAdmin?.id + }).then().catch() + + logToCloudWatch( + 'success', + 'organization admin', + 'Validate token to reset password for organization admin id ' + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + res.send("You can now set your new password by making a POST request to /reset-password/:id with your new password in the request body."); + } catch (error) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Validate token to reset password for organization admin id ' + res.locals.organizationAdmin?.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'organization admin', + 'Validate token to reset password for organization admin id ' + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.status(500).send("Invalid or expired token."); + } +}); + +router.post("/reset-password/:id", authenticate, authorize("POST_voluntaryWork"), validateAdminId, async (req, res, next) => { + const id = req.params.id; + const token = req.cookies['reset-password'] || ''; + const password = req.body.password; + // if(!password || !isValidPassword(password) )next() bad request + resetPassword(id, token, password).then(data => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Reset password for organization admin id ' + res.locals.organizationAdmin?.id + }).then().catch() + + logToCloudWatch( + 'success', + 'organization admin', + 'Reset password for organization admin id ' + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.status(200).send(data) + }).catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Reset password for organization admin id ' + res.locals.organizationAdmin?.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'organization admin', + 'Reset password for organization admin id ' + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + // res.send(err) + }) +}); + +/** + * @swagger + * tags: + * name: OrganizationAdmin + * description: The OrganizationAdmin managing API + */ + + +/** + * @swagger + * /organizationAdmin/login: + * post: + * summary: Login an organization admin + * tags: [OrganizationAdmin] + * requestBody: + * description: Organization admin data to sign up + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * email: + * type: string + * id: + * type: string + * example: + * name: "Admin 1" + * email: "tamimitarteel@gmail.com" + * id: "89588e2a-7f6e-42cc-b3d2-943e04966eb6" + * responses: + * 200: + * description: Organization admin loged in successfully + * 401: + * description: Organization admin unauthorized + * 400: + * description: Bad request + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /organizationAdmin/logout: + * get: + * summary: Log out an organization admin + * tags: [OrganizationAdmin] + * responses: + * 200: + * description: Organization admin loged out successfully + * 401: + * description: Organization admin unauthorized + */ + +/** + * @swagger + * /organizationAdmin/search: + * get: + * summary: Get organization admin based on the provided query parameters + * tags: [OrganizationAdmin] + * parameters: + * - in: query + * name: id + * schema: + * type: string + * description: Filter organization admin by ID + * - in: query + * name: name + * schema: + * type: string + * description: Filter organization admin by name + * - in: query + * name: email + * schema: + * type: string + * description: Filter organization admin by email + * - in: query + * name: organizationName + * schema: + * type: string + * description: Filter organization admin by organization name + * responses: + * 200: + * description: Find organization admin + * content: + * application/json: + * schema: + * type: object + * properties: + * organizationAdmin: + * type: object + * example: + * organizationProfile: + * - name: "Admin 1" + * email: "tamimitarteel@gamil.com" + * createdAt: "22023-10-26T22:26:29.365Z" + * + * 404: + * description: Organization Admin not found + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /organizationAdmin/{id}: + * delete: + * summary: Delete an organization admin by ID + * tags: [OrganizationAdmin] + * parameters: + * - in: path + * name: id + * schema: + * type: string + * required: true + * description: ID of the organization admin to delete + * responses: + * 200: + * description: Organization admin deleted successfully + * 404: + * description: Organization admin not found + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /organizationAdmin/signup: + * post: + * summary: Sign up an organization admin + * tags: [OrganizationAdmin] + * requestBody: + * description: Organization admin data to sign up + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * email: + * type: string + * password: + * type: string + * organizationId: + * type: string + * # Add other properties from NSOrganizationAdmin.Item as needed + * example: + * name: "Admin 1" + * email: "tamimitarteel@gmail.com" + * password: "Tareel123>>" + * organizationId: "8995852d-5b2e-4aff-a6fe-3e96cab49add" + * responses: + * 201: + * description: Organization admin signed up successfully + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * data: + * # Define the structure of the returned data here + * example: + * message: "Organization admin signs up successfully" + * data: + * name: "Admin 1" + * email: "tamimitarteel@gmail.com" + * roles: + * id: 2 + * name: "admin" + * createdAt: "2023-10-25T21:42:11.724Z" + * orgProfile: + * id: "8995852d-5b2e-4aff-a6fe-3e96cab49add" + * name: "Test" + * description: "test test" + * createdAt: "2023-10-26T11:00:41.632Z" + * id: "f7ee8f20-eabe-47a7-bd9a-30594765dbf7" + * createdAt: "2023-10-26T20:07:06.810Z" + * 400: + * description: Bad request, validation failed + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /organizationAdmin/{id}: + * put: + * summary: Edit an organization admin by ID + * tags: [OrganizationAdmin] + * parameters: + * - in: path + * name: id + * schema: + * type: string + * required: true + * description: ID of the organization admin to edit + * requestBody: + * description: Organization admin data to update + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * email: + * type: string + * newPassword: + * type: string + * oldPassword: + * type: string + * organizationName: + * type: string + * example: + * name: "New Name" + * + * responses: + * 200: + * description: Organization admin edited successfully + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: + * name: "Updated Organization Admin Name" + * + * 404: + * description: Organization admin not found + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /organizationAdmin/forget-password: + * get: + * summary: Send a password reset link to a organizationAdmin's email + * tags: [OrganizationAdmin] + * security: + * - BearerAuth: [] + * responses: + * 200: + * description: Password reset link sent successfully + * content: + * text/plain: + * schema: + * type: string + * example: Password reset link has been sent to your email + * 401: + * description: OrganizationAdmin unauthorized + * 403: + * description: You don't have the permission. + * 500: + * description: Internal Server Error + */ + +/** + * @swagger + * /organizationAdmin/reset-password/{id}/{token}: + * get: + * summary: Validate a password reset token for a organizationAdmin + * tags: [OrganizationAdmin] + * parameters: + * - name: id + * in: path + * required: true + * description: The ID of the organizationAdmin. + * schema: + * type: string + * - name: token + * in: path + * required: true + * description: The password reset token. + * schema: + * type: string + * responses: + * 200: + * description: Token validated successfully + * content: + * text/plain: + * schema: + * type: string + * example: You can now set your new password by making a POST request to /reset-password/{id} with your new password in the request body. + * 401: + * description: OrganizationAdmin unauthorized + * 403: + * description: You don't have the permission. + + * 500: + * description: Invalid or expired token. + */ + +/** + * @swagger + * /organizationAdmin/reset-password/{id}: + * post: + * summary: Reset the password for a organizationAdmin + * tags: [OrganizationAdmin] + * parameters: + * - name: id + * in: path + * required: true + * description: The ID of the organizationAdmin. + * schema: + * type: string + + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * password: + * type: string + * responses: + * 200: + * description: Password updated successfully + * content: + * text/plain: + * schema: + * type: string + * example: Password updated successfully!! + * 401: + * description: OrganizationAdmin unauthorized + * 403: + * description: You don't have the permission. + * 400: + * description: Your request is BAD, + * 500: + * description: Internal Server Error + */ + +export default router; \ No newline at end of file diff --git a/src/routes/organizationProfile.ts b/src/routes/organizationProfile.ts new file mode 100644 index 00000000..04830839 --- /dev/null +++ b/src/routes/organizationProfile.ts @@ -0,0 +1,472 @@ +import express from "express"; +import { createOrganizationProfile, deleteOrganizationProfile, editOrganizationProfile, getOrganizationProfile, searchOrganizationProfile } from "../controllers/OrganizationProfile .js"; +import { authorize, checkAdmin } from "../middleware/auth/authorize.js"; +import { validateOrgId, validateOrganizationProfile } from "../middleware/validation/organizationProfile.js"; +import { log } from "../controllers/dataBaseLogger.js"; +import { NSLogs } from "../../types/logs.js"; +import { logToCloudWatch } from "../controllers/AWSServices/CloudWatchLogs.js"; + +const router = express.Router(); + +router.post('/', authorize("POST_organizationProfile"), validateOrganizationProfile, (req, res, next) => { + createOrganizationProfile(req.body).then((data) => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Create Organization Profile ' + data.name + }).then().catch() + + logToCloudWatch( + 'success', + 'organization profile', + 'Create Organization Profile ' + data.name, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.status(201).send({message:"Organization Profile created successfully!!" , data}) + }).catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Create Organization Profile ' + req.body.name + }).then().catch() + + logToCloudWatch( + 'failed', + 'organization profile', + 'Create Organization Profile ' + req.body.name, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.delete('/:id', validateOrgId, authorize("DELETE_organizationProfile"), async (req, res, next) => { + const id = (req.params.id?.toString()); + + deleteOrganizationProfile(id) + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Delete Organization Profile with id: ' + id + }).then().catch() + + logToCloudWatch( + 'success', + 'organization profile', + 'Volunteer registered successfully!', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Delete Organization Profile with id: ' + id + }).then().catch() + + logToCloudWatch( + 'failed', + 'organization profile', + 'Volunteer registered successfully!', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.put("/:id", validateOrgId, authorize("PUT_organizationProfile"), async (req, res, next) => { + editOrganizationProfile(req.body).then(() => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Edit Organization Profile with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'organization profile', + 'Volunteer registered successfully!', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.status(200).send("Organization Profile edited successfully!!") + }).catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Edit Organization Profile with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'organization profile', + 'Volunteer registered successfully!', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.get('/search', authorize("GET_organizationProfiles"), async (req, res, next) => { + const payload = { + page: req.query.page?.toString() || '1', + pageSize: req.query.pageSize?.toString() || '10', + id: req.query.id?.toString() || '', + name: req.query.name?.toString() || '', + adminName: req.query.adminName?.toString() || '' + }; + + searchOrganizationProfile(payload) + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Search Organization Profiles' + }).then().catch() + + logToCloudWatch( + 'success', + 'organization profile', + 'Search Organization Profiles', + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + res.status(200).send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Search Organization Profiles' + }).then().catch() + + logToCloudWatch( + 'failed', + 'organization profile', + 'Search Organization Profiles', + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + next(err); + }); +}); + +router.get('/', authorize("GET_organizationProfiles"), async (req, res, next) => { + const payload = { + page: req.query.page?.toString() || '1', + pageSize: req.query.pageSize?.toString() || '10', + }; + + getOrganizationProfile(payload) + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Get Organization Profiles' + }).then().catch() + + logToCloudWatch( + 'success', + 'organization profile', + 'Get Organization Profiles', + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Get Organization Profiles' + }).then().catch() + + logToCloudWatch( + 'failed', + 'organization profile', + 'Get Organization Profiles', + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + next(err); + }); +}); + +/** + * @swagger + * tags: + * name: OrganizationProfile + * description: The OrganizationProfile managing API + */ + + + +/** + * @swagger + * /organizationProfile: + * get: + * summary: Get all organization profiles + * tags: [OrganizationProfile] + * parameters: + * - in: query + * name: page + * schema: + * type: string + * description: Page number for pagination + * - in: query + * name: pageSize + * schema: + * type: string + * description: Number of items per page + * responses: + * 200: + * description: Success + * content: + * application/json: + * schema: + * type: object + * properties: + * page: + * type: integer + * pageSize: + * type: integer + * total: + * type: integer + * organizationProfiles: + * type: array + * items: + * type: object + * example: + * page: 1 + * pageSize: 10 + * total: 3 + * organizationProfiles: + * - name: "Organization 1" + * description: "this is a test" + * createdAt: 2023-10-26T09:58:16.590Z + * - name: "Organization 2" + * description: "this is a test" + * createdAt: 2023-10-26T09:58:55.481Z + * - name: "Organization 3" + * description: "this is a test" + * createdAt: 2023-10-26T09:59:23.481Z + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /organizationProfile/search: + * get: + * summary: Get organization profile based on the provided query parameters + * tags: [OrganizationProfile] + * parameters: + * - in: query + * name: id + * schema: + * type: string + * description: Filter organization profile by ID + * - in: query + * name: name + * schema: + * type: string + * description: Filter organization profile by name + * - in: query + * name: adminName + * schema: + * type: string + * description: Filter organization profile by admin name + * responses: + * 200: + * description: Find organization profile + * content: + * application/json: + * schema: + * type: object + * properties: + * organizationProfile: + * type: object + * example: + * organizationProfile: + * - id: "8995852d-5b2e-4aff-a6fe-3e96cab49add" + * name: "Test 1" + * description: "this is a test" + * createdAt: "2023-10-26T11:00:41.632Z" + * + * 404: + * description: Organization Profile not found + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /organizationProfile/{id}: + * delete: + * summary: Delete an organization profile by ID + * tags: [OrganizationProfile] + * parameters: + * - in: path + * name: id + * schema: + * type: string + * required: true + * description: ID of the organization profile to delete + * responses: + * 200: + * description: Organization profile deleted successfully + * 404: + * description: Organization profile not found + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /organizationProfile: + * post: + * summary: Create a new organization profile + * tags: [OrganizationProfile] + * requestBody: + * description: Organization profile data to create + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * description: + * type: string + * # Add other properties from NSOganizationProfile.Item as needed + * example: + * name: "Organization Profile Name" + * description: "this is a test" + * responses: + * 201: + * description: Organization profile created successfully + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * data: + * # Define the structure of the returned data here + * example: + * message: "Organization profile created successfully" + * data: + * name: "Organization Profile Name" + * description: "this is a test" + * id: 03b080e6-87d6-4211-9e75-1c8e8c089ed6 + * createdAt: 2023-10-26T10:03:30.233Z + * 400: + * description: Bad request, validation failed + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /organizationProfile/{id}: + * put: + * summary: Edit an organization profile by ID + * tags: [OrganizationProfile] + * parameters: + * - in: path + * name: id + * schema: + * type: string + * required: true + * description: ID of the organization profile to edit + * requestBody: + * description: Organization profile data to update + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * description: + * type: string + * example: + * name: "New Name" + * responses: + * 200: + * description: Organization Profile edited successfully + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: + * name: "Updated Organization Profile Name" + * 404: + * description: Organization Profile not found + * 401: + * description: You are nauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +export default router; \ No newline at end of file diff --git a/src/routes/permission.ts b/src/routes/permission.ts new file mode 100644 index 00000000..2326479b --- /dev/null +++ b/src/routes/permission.ts @@ -0,0 +1,373 @@ +import express from 'express'; +import { createPermission, deletePermission, editPermission, getPermissions } from '../controllers/permission.js'; +import { authorize } from '../middleware/auth/authorize.js'; +import { validatePermission, validatePermissionId } from '../middleware/validation/permission.js'; +import { log } from '../controllers/dataBaseLogger.js'; +import { NSLogs } from '../../types/logs.js'; +import { logToCloudWatch } from '../controllers/AWSServices/CloudWatchLogs.js'; + +var router = express.Router(); + +router.post('/', authorize("POST_permission"), validatePermission, (req, res, next) => { + createPermission(req.body).then((data) => { + + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Create Permission ' + req.body.name + }).then().catch() + + logToCloudWatch( + 'success', + 'permission', + 'Create Permission ' + req.body.name, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.status(201).send({ message: "Permission created successfully!!", data }) + }).catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Create Permission ' + req.body.name + }).then().catch() + + logToCloudWatch( + 'failed', + 'permission', + 'Create Permission ' + req.body.name, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.delete('/:id', validatePermissionId, authorize("DELETE_permission"), async (req, res, next) => { + const id = Number(req.params.id?.toString()); + + deletePermission(id) + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Delete Permission with id: ' + id + }).then().catch() + + logToCloudWatch( + 'success', + 'permission', + 'Delete Permission with id: ' + id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name, + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Delete Permission with id: ' + id + }).then().catch() + + logToCloudWatch( + 'failed', + 'permission', + 'Delete Permission with id: ' + id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name, + ).then().catch() + + next(err); + }); +}) + +router.put("/:id", authorize("PUT_permission"), validatePermissionId, async (req, res, next) => { + editPermission({ ...req.body, id: req.params.id?.toString() }).then(() => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Edit Permission with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'permission', + 'Edit Permission with id: ' + req.params.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.status(200).send("Permission edited successfully!!") + }).catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Edit Permission with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'permission', + 'Edit Permission with id: ' + req.params.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.get('/', authorize("GET_permissions"), async (req, res, next) => { + const payload = { + page: req.query.page?.toString() || '1', + pageSize: req.query.pageSize?.toString() || '10', + id: Number(req.query.id) || 0, + name: req.query.name?.toString() || "" + }; + + getPermissions(payload) + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Get Permission/s' + }).then().catch() + + logToCloudWatch( + 'success', + 'permission', + 'Get Permission/s', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Get Permission/s' + }).then().catch() + + logToCloudWatch( + 'failed', + 'permission', + 'Get Permission/s', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +/** + * @swagger + * tags: + * name: Permission + * description: The permission managing API + */ + + + +/** + * @swagger + * /permission: + * get: + * summary: Get permissions based on the provided query parameters or get all permissions + * tags: [Permission] + * parameters: + * - in: query + * name: page + * schema: + * type: string + * description: Page number for pagination (optional) + * - in: query + * name: pageSize + * schema: + * type: string + * description: Number of items per page (optional) + * - in: query + * name: id + * schema: + * type: number + * description: Filter permissions by ID (optional) + * - in: query + * name: name + * schema: + * type: string + * description: Filter permissions by name (optional) + * responses: + * 200: + * description: List of permissions or a single permission + * content: + * application/json: + * schema: + * type: object + * properties: + * page: + * type: integer + * pageSize: + * type: integer + * total: + * type: integer + * permissions: + * type: array + * items: + * type: object + * example: + * page: 1 + * pageSize: 10 + * total: 2 + * permissions: + * - id: 1 + * name: "Permission 1" + * - id: 2 + * name: "Permission 2" + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 404: + * description: Permission not found + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /permission/{id}: + * delete: + * summary: Delete a permission by ID + * tags: [Permission] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the permission to delete + * responses: + * 200: + * description: Permission deleted successfully + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 404: + * description: Permission not found + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /permission: + * post: + * summary: Create a new permission + * tags: [Permission] + * requestBody: + * description: Permission data to create + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * required: + * true + * example: + * name: "Permission Name" + * responses: + * 201: + * description: Permission created successfully + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * data: + * # Define the structure of the returned data here + * example: + * message: "Permission created successfully" + * data: + * id: 1 + * name: "Permission Name" + * 400: + * description: Bad request, validation failed + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /permission/{id}: + * put: + * summary: Edit a permission by ID + * tags: [Permission] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the permission to edit + * requestBody: + * description: Permission data to update + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * required: + * true + * example: + * name: "Updated Permission Name" + * responses: + * 200: + * description: Permission edited successfully + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 404: + * description: Permission not found + * 500: + * description: Something went wrong + */ + + +export default router; + diff --git a/src/routes/role.ts b/src/routes/role.ts new file mode 100644 index 00000000..2e03f0a4 --- /dev/null +++ b/src/routes/role.ts @@ -0,0 +1,370 @@ +import express from 'express'; +import { createRole, deleteRole, editRole, getRoles } from '../controllers/role.js'; +import { NSRole } from '../../types/role.js'; +import { authorize } from '../middleware/auth/authorize.js'; +import { validateEditedRole, validateRole, validateRoleId } from '../middleware/validation/role.js'; +import { log } from '../controllers/dataBaseLogger.js'; +import { NSLogs } from '../../types/logs.js'; +import { logToCloudWatch } from '../controllers/AWSServices/CloudWatchLogs.js'; + +var router = express.Router(); + +router.post('/', authorize("POST_role"), validateRole, (req, res, next) => { + createRole(req.body).then((data) => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Create Role ' + req.body.name + }).then().catch() + + logToCloudWatch( + 'success', + 'role', + 'Create Role ' + req.body.name, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.status(201).send({message:"Role created successfully!!",data}) + }).catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Create Role ' + req.body.name + }).then().catch() + + logToCloudWatch( + 'failed', + 'role', + 'Create Role ' + req.body.name, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.delete('/:id', validateRoleId, authorize("DELETE_role"), async (req, res, next) => { + const id = Number(req.params.id?.toString()); + + deleteRole(id) + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Delete Role with id: ' + id + }).then().catch() + + logToCloudWatch( + 'success', + 'role', + 'Delete Role with id: ' + id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Delete Role with id: ' + id + }).then().catch() + + logToCloudWatch( + 'failed', + 'role', + 'Delete Role with id: ' + id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}) + +router.put("/:id", authorize("PUT_role"), validateEditedRole, async (req, res, next) => { + editRole({ ...req.body, id: req.params.id?.toString() }).then(() => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Edit Role with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'role', + 'Edit Role with id: ' + req.params.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.status(200).send("Role edited successfully!!") + }).catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Edit Role with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'role', + 'Edit Role with id: ' + req.params.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.get('/', authorize("GET_roles"), async (req, res, next) => { + const payload = { + page: req.query.page?.toString() || '1', + pageSize: req.query.pageSize?.toString() || '10', + id: Number(req.query.id) || 0, + name: req.query.name?.toString() as NSRole.Type + }; + + getRoles(payload) + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Get Role/s' + }).then().catch() + + logToCloudWatch( + 'success', + 'role', + 'Get Role/s', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Get Role/s' + }).then().catch() + + logToCloudWatch( + 'failed', + 'role', + 'Get Role/s', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name, + ).then().catch() + + next(err); + }); +}); + +export default router; + +/** + * @swagger + * tags: + * name: Role + * description: The permission managing API + */ + +/** + * @swagger + * /role: + * post: + * summary: Create a new role with associated permissions + * tags: [Role] + * requestBody: + * description: Role data to create + * required: true + * content: + * application/json: + * example: + * name: "Role Name" + * permissionsId: [1, 2] + * responses: + * 201: + * description: Role created successfully + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: + * message: "Role created successfully" + * data: + * id: 1 + * name: "Role Name" + * permissions: [ + * { + * id: 1, + * name: "Permission 1" + * }, + * { + * id: 2, + * name: "Permission 2" + * } + * ] + * 400: + * description: Bad Request, validation failed + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /role/{id}: + * delete: + * summary: Delete a role by ID + * tags: [Role] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the role to delete + * responses: + * 200: + * description: Role deleted successfully + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 404: + * description: Role not found + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /role/{id}: + * put: + * summary: Edit a role by ID + * tags: [Role] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the role to edit + * requestBody: + * description: Role data to update + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * example: + * name: "Updated Role Name" + * responses: + * 200: + * description: Role edited successfully + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 404: + * description: Role not found + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /: + * get: + * summary: Get roles based on the provided query parameters or get all roles + * tags: [Role] + * parameters: + * - in: query + * name: page + * schema: + * type: string + * description: Page number for pagination (optional) + * - in: query + * name: pageSize + * schema: + * type: string + * required: false + * description: Number of items per page (optional) + * - in: query + * name: id + * schema: + * type: number + * description: Filter roles by ID (optional) + * - in: query + * name: name + * schema: + * type: string + * description: Filter roles by name (optional) + * responses: + * 200: + * description: List of roles or a single role + * content: + * application/json: + * schema: + * type: object + * properties: + * page: + * type: integer + * pageSize: + * type: integer + * total: + * type: integer + * roles: + * type: array + * items: + * type: object + * example: + * page: 1 + * pageSize: 10 + * total: 2 + * roles: + * - id: 1 + * name: "Role 1" + * - id: 2 + * name: "Role 2" + * 404: + * description: Role not found + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ diff --git a/src/routes/users.ts b/src/routes/users.ts deleted file mode 100644 index 70d8be46..00000000 --- a/src/routes/users.ts +++ /dev/null @@ -1,51 +0,0 @@ -// import express from 'express'; -// import { getAllUsersController, loginController, signupController } from '../controllers/user.js'; -// const router = express.Router(); - -// /* POST Signup user. */ -// router.post("/signup", async (req: express.Request, res: express.Response) => { -// try { -// if (req.body.userName && req.body.password && req.body.email) { -// await signupController(req.body) -// res.status(200).json("User created successfully"); -// } else { -// res.status(400).json("All fields are required"); -// } -// } catch (error) { -// console.log(error); -// if (error !== "user already exists") { -// res.status(500).json("Internal server error"); -// } -// res.status(409).json("user already exists"); -// } -// }); - -// /* POST Login user. */ -// router.post("/login", async (req: express.Request, res: express.Response) => { -// try { -// if (req.body.email && req.body.password) { -// const data = await loginController(req.body) -// res.status(200).json(data); -// } else { -// res.status(400).json("All fields are required"); -// } -// } catch (error) { -// console.log(error); -// res.status(400).json("invalid email or password"); -// } -// }); - - -// /* GET All users. */ -// router.get("/", async (req: express.Request, res: express.Response) => { -// try { -// const users = await getAllUsersController(); -// res.status(200).json({ users: users[0], count: users[1] }); -// } catch (error) { -// console.log(error); -// res.status(500).json("Internal server error"); -// } -// }) - - -// export default router; diff --git a/src/routes/voluntaryWork.ts b/src/routes/voluntaryWork.ts new file mode 100644 index 00000000..762640fd --- /dev/null +++ b/src/routes/voluntaryWork.ts @@ -0,0 +1,2950 @@ +import express from 'express'; +import { createVoluntaryWork, deleteFeedback, deleteImage, deleteRating, deleteVoluntaryWork, deregisterVoluntaryWork, editVoluntaryWork, findSmallestSufficientTeam, generateCertificate, getAnalysis, getFeedbackAndRating, getImages, getOrganizationAnalysis, getRecommendation, getVoluntaryWork, getVoluntaryWorks, getVoluntaryWorksForVolunteer, putFeedback, putRating, registerByOrganizationAdmin, registerByVolunteer, sendingEmails, volunteerReminder } from '../controllers/voluntaryWork.js'; +import { NSVolunteer } from '../../types/volunteer.js'; +import { NSVoluntaryWork } from '../../types/voluntaryWork.js'; +import { authorize, checkParticipation } from '../middleware/auth/authorize.js'; +import { validateDeleteFromS3, validateEditedVoluntaryWork, validateRating, validateVoluntaryWork, validateVoluntaryWorkId } from '../middleware/validation/voluntaryWork.js'; +import { log } from '../controllers/dataBaseLogger.js'; +import { NSLogs } from '../../types/logs.js'; +import { logToCloudWatch } from '../controllers/AWSServices/CloudWatchLogs.js'; +import { deleteFromS3, loadFromS3, putCertificateTemplate, putImages } from '../controllers/AWSServices/S3.js'; +import { searchOrganizationProfile } from '../controllers/OrganizationProfile .js'; +import { validateVolunteerId } from '../middleware/validation/volunteer.js'; +import { sendEmail } from '../controllers/AWSServices/SES.js'; +import { VoluntaryWork } from '../db/entities/VoluntaryWork.js'; +import { Volunteer } from '../db/entities/Volunteer.js'; +import { SkillTag } from '../db/entities/SkillTag.js'; +import baseLogger from '../../logger.js'; +import { validateOrgId, validateOrganizationProfile } from '../middleware/validation/organizationProfile.js'; + +var router = express.Router(); + +router.post('/', authorize("POST_voluntaryWork"), validateVoluntaryWork, (req, res, next) => { + createVoluntaryWork({ ...req.body, creatorId: res.locals.volunteer?.id || res.locals.organizationAdmin?.id }).then((data) => { + sendingEmails(data.name).then(()=>{ + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Create Voluntary Work ' + req.body.name + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Create Voluntary Work ' + req.body.name, + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + res.status(201).send({ message: "Voluntary work created successfully!!", data }) + }).catch(err=>{ + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Sending emails to announce new voluntary work ' + req.body.name + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Sending emails to announce new voluntary work ' + req.body.name, + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + next(err); + }) + + }).catch(err => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Create Voluntary Work ' + req.body.name + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Create Voluntary Work ' + req.body.name, + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + next(err); + }); +}); + +router.put("/:id", authorize("PUT_voluntaryWork"), validateEditedVoluntaryWork, async (req, res, next) => { + editVoluntaryWork({ ...req.body, id: req.params.id?.toString() }).then(() => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Edit Voluntary Work with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Edit Voluntary Work with id: ' + req.params.id, + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + res.status(201).send("Voluntary Work edited successfully!!") + }).catch(err => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Edit Voluntary Work with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + + 'Edit Voluntary Work with id: ' + req.params.id, + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + next(err); + }); +}); + +router.delete('/:id', validateVoluntaryWorkId, authorize("DELETE_voluntaryWork"), async (req, res, next) => { + const id = Number(req.params.id?.toString()); + + deleteVoluntaryWork(id) + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Delete Voluntary Work with id: ' + id + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Delete Voluntary Work with id: ' + id, + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Delete Voluntary Work with id: ' + id + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Delete Voluntary Work with id: ' + id, + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + next(err); + }); +}) + +router.put("/image/:id", validateVoluntaryWorkId, authorize("PUT_images"), async (req, res, next) => { + const images = req.files?.image; + if (!images) { + return res.status(400).send("No images provided."); + } + + try { + const uploadedFiles = Array.isArray(images) ? images : [images]; + + const payload = { page: "", pageSize: "", id: "", name: "", adminName: res.locals.organizationAdmin.name }; + const organization = await searchOrganizationProfile(payload); + const organizationName = organization?.name || req.body.organizationName; + + await putImages(Number(req.params.id), uploadedFiles, organizationName); + + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Add images to voluntary work with id ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Add images to voluntary work with id ' + req.params.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.status(201).send("Images added successfully!!"); + } catch (err) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Add images to voluntary work with id ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Add images to voluntary work with id ' + req.params.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + } +}); + +router.get('/image/:id', validateVoluntaryWorkId, async (req, res, next) => { + getImages(Number(req.params.id)) + .then(data => { + log({ + userId: res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + userName: res.locals.volunteer?.name || res.locals.organizationAdmin?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Get image/s for voluntary work with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Get image/s', + res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + res.locals.volunteer?.name || res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + userName: res.locals.volunteer?.name || res.locals.organizationAdmin?.name, + userType: res.locals.volunteer?.type as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Get image/s for voluntary work with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Get image/s', + res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + res.locals.volunteer?.name || res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.delete('/image/:id', validateVoluntaryWorkId, authorize("PUT_images"), validateDeleteFromS3, async (req, res, next) => { + + const id = Number(req.params.id?.toString()); + const voluntaryWork = await getVoluntaryWork({ id }); + const organizationProfile = await searchOrganizationProfile({ page: "", pageSize: "", id: "", name: "", adminName: res.locals.organizationAdmin.name }); + const key = `${organizationProfile?.name || req.body.organizationName}/${voluntaryWork?.name}/${req.body.imageName}.png` + + deleteImage(id, req.body.imageName + '.png').then(() => { + deleteFromS3(key, 'image') + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Delete image from Voluntary Work with id: ' + id + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Delete image from Voluntary Work with id: ' + id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.status(200).send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Delete image from Voluntary Work with id: ' + id + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Delete image from Voluntary Work with id: ' + id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); + + }).catch(err => { + baseLogger.error(err); + next(err); + }) + + +}) + +router.post("/rating/:id", validateVoluntaryWorkId, authorize("DELETE_voluntaryWork"), async (req, res, next) => { + volunteerReminder(Number(req.params.id)).then(() => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Reminder to add rating and feedback for voluntary work with id: ' + req.params.id, + + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Reminder to add rating and feedback for voluntary work with id: ' + req.params.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.status(201).send("Create remainder for rate and feedback successfully!!") + }).catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Reminder to add rating and feedback for voluntary work with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Reminder to add rating and feedback for voluntary work with id: ' + req.params.id, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.put("/rating/:id", validateVoluntaryWorkId, authorize("PUT_rating"), checkParticipation,validateRating, async (req, res, next) => { + putRating(Number(req.params.id), Number(req.body.rating), res.locals.volunteer?.name).then(() => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: res.locals.volunteer?.type as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Add or update Rating to voluntary work with id' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Add or update Rating to voluntary work with id' + req.params.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + res.status(201).send("Rating added or updated successfully!!") + }).catch(err => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: res.locals.volunteer?.type as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Add or update Rating to voluntary work with id' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Add or update Rating to voluntary work with id' + req.params.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + next(err); + }); +}); + +router.put("/feedback/:id", validateVoluntaryWorkId, authorize("PUT_feedback"), checkParticipation, async (req, res, next) => { + if (!req.body.feedback)res.status(400).send("Feedback is required!") + putFeedback(Number(req.params.id), req.body.feedback, res.locals.volunteer?.name).then(() => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: res.locals.volunteer?.type as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Add or update feedback to voluntary work with id' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Add or update feedback to voluntary work with id' + req.params.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + res.status(201).send("Feedback or update added successfully!!") + }).catch(err => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name, + userType: res.locals.volunteer?.type as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Add or update feedback to voluntary work with id' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Add or update feedback to voluntary work with id' + req.params.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + next(err); + }); +}); + +router.delete("/rating/:id", validateVoluntaryWorkId, authorize("PUT_rating"), checkParticipation, async (req, res, next) => { + deleteRating(Number(req.params.id), res.locals.volunteer?.name).then(() => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: res.locals.volunteer?.type as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Delete Rating to voluntary work with id' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Delete Rating to voluntary work with id' + req.params.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + res.status(200).send("Rating deleted successfully!!") + }).catch(err => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: res.locals.volunteer?.type as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Delete Rating to voluntary work with id' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Delete Rating to voluntary work with id' + req.params.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + next(err); + }); +}); + +router.delete("/feedback/:id", validateVoluntaryWorkId, authorize("PUT_rating"), checkParticipation, async (req, res, next) => { + deleteFeedback(Number(req.params.id), res.locals.volunteer?.name).then(() => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: res.locals.volunteer?.type as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Delete Feedback to voluntary work with id' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Delete Feedback to voluntary work with id' + req.params.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + res.status(200).send("Feedback deleted successfully!!") + }).catch(err => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: res.locals.volunteer?.type as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Delete Feedback to voluntary work with id' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Delete Feedback to voluntary work with id' + req.params.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + next(err); + }); +}); + +router.get('/search', authorize("GET_voluntaryWorks"), async (req, res, next) => { + + const payload = { + page: req.query.page?.toString() || '1', + pageSize: req.query.pageSize?.toString() || '10', + id: Number(req.query.id) || 0, + name: req.query.name?.toString() || '', + time: ((Array.isArray(req.query.time) ? req.query.time : [req.query.time]).filter(Boolean)) as NSVolunteer.AvailableTime[], + location: (typeof req.query.location === 'string' ? req.query.location : ''), + days: (Array.isArray(req.query.days) ? req.query.days : [req.query.days]).filter(Boolean) as NSVolunteer.AvailableDays[], + avgRating: Number(req.query.avgRating) || 0, + status: req.query.status as NSVoluntaryWork.StatusType, + skills: (Array.isArray(req.query.skills) ? req.query.skills : [req.query.skills]).filter(Boolean) as string[], + startedDate: req.query.startedDate?.toString() || "", + finishedDate: req.query.finishedDate?.toString() || "", + capacity: Number(req.query.capacity) || 0, + finishedAfter: "", finishedBefore: "", + startedAfter: "", startedBefore: "", creatorId: "", + avgRatingMore: Number(req.query.avgRatingMore) || 0, + avgRatingLess: Number(req.query.avgRatingLess) || 0, + isSkillsRequired: (req.query.startedDate?.toString() || false) as boolean + }; + + getVoluntaryWorks(payload) + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Search Voluntary Work/s' + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Search Voluntary Work/s', + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Search Voluntary Work/s' + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Search Voluntary Work/s', + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + next(err); + }); +}); + +router.get('/advanced-search', authorize("GET_analysis"), async (req, res, next) => { + + const payload = { + page: req.query.page?.toString() || '1', + pageSize: req.query.pageSize?.toString() || '10', + id: Number(req.query.id) || 0, + name: req.query.name?.toString() || '', + time: ((Array.isArray(req.query.time) ? req.query.time : [req.query.time]).filter(Boolean)) as NSVolunteer.AvailableTime[], + location: (typeof req.query.location === 'string' ? req.query.location : ''), + days: (Array.isArray(req.query.days) ? req.query.days : [req.query.days]).filter(Boolean) as NSVolunteer.AvailableDays[], + avgRating: Number(req.query.avgRating) || 0, + status: req.query.status as NSVoluntaryWork.StatusType, + skills: (Array.isArray(req.query.skills) ? req.query.skills : [req.query.skills]).filter(Boolean) as string[], + startedDate: req.query.startedDate?.toString() || "", + finishedDate: req.query.finishedDate?.toString() || "", + capacity: Number(req.query.capacity) || 0, + finishedAfter: req.query.finishedDate?.toString() || "", + finishedBefore: req.query.finishedBefore?.toString() || "", + startedAfter: req.query.startedAfter?.toString() || "", + startedBefore: req.query.startedBefore?.toString() || "", + avgRatingMore: Number(req.query.avgRatingMore) || 0, + avgRatingLess: Number(req.query.avgRatingLess) || 0, + creatorId: req.query.creatorId?.toString() || "", + isSkillsRequired: (req.query.startedDate?.toString() || false) as boolean + }; + + getVoluntaryWorks(payload) + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Advanced search for Voluntary Work/s' + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Advanced search for Voluntary Work/s', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: "root" as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Advanced search for Voluntary Work/s' + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Advanced search for Voluntary Work/s', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.get('/analysis', authorize("GET_analysis"), async (req, res, next) => { + getAnalysis() + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Analyze the system ' + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Analyze the system ', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: "root" as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Analyze the system ' + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Analyze the system ', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.get('/analysis/:id', authorize("DELETE_organizationProfile"), validateOrgId, async (req, res, next) => { + getOrganizationAnalysis(req.params.id.toString()) + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: 'root' as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Analyze the organization voluntary works with id ' + req.params.id.toString() + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Analyze the organization voluntary works ', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: "root" as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Analyze the organization voluntary works with id ' + req.params.id.toString() + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Analyze the organization voluntary works ', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.get('/recommendation', authorize("GET_recommendation"), async (req, res, next) => { + const skillTags: SkillTag[] = res.locals.volunteer.volunteerProfile.skillTags; + const payload = { + page: req.query.page?.toString() || '1', + pageSize: req.query.pageSize?.toString() || '10', + time: res.locals.volunteer.availableTime as NSVolunteer.AvailableTime[], + location: res.locals.volunteer.availableLocation, + days: res.locals.volunteer.availableDays as NSVolunteer.AvailableDays[], + status: "Pending" as NSVoluntaryWork.StatusType, + skillTags: skillTags.map(skillTag => skillTag.id) + }; + + getRecommendation(payload) + .then(data => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: res.locals.volunteer?.type as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Get recommendation' + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Get recommendation', + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: res.locals.volunteer?.type as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Get recommendation' + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Get recommendation', + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + next(err); + }); +}); + +router.get('/volunteer/:id', validateVolunteerId, async (req, res, next) => { + getVoluntaryWorksForVolunteer(req.params.id) + .then(data => { + log({ + userId: res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + userName: res.locals.volunteer?.name || res.locals.organizationAdmin?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Get voluntary works for volunteer with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Get voluntary works for volunteer', + res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + res.locals.volunteer?.name || res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + userName: res.locals.volunteer?.name || res.locals.organizationAdmin?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Get voluntary works for volunteer with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Get voluntary works for volunteer', + res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + res.locals.volunteer?.name || res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.get('/rating-and-feedback/:id', validateVoluntaryWorkId, async (req, res, next) => { + getFeedbackAndRating(Number(req.params.id.toString())) + .then(data => { + log({ + userId: res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + userName: res.locals.volunteer?.name || res.locals.organizationAdmin?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Get rating and feedback for voluntary work with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Get rating and feedback for voluntary work', + res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + res.locals.volunteer?.name || res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + userName: res.locals.volunteer?.name || res.locals.organizationAdmin?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Get rating and feedback for voluntary work with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Get rating and feedback for voluntary work', + res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + res.locals.volunteer?.name || res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.get('/sufficient-team/:id', validateVoluntaryWorkId, async (req, res, next) => { + findSmallestSufficientTeam(Number(req.params.id.toString())) + .then(data => { + log({ + userId: res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + userName: res.locals.volunteer?.name || res.locals.organizationAdmin?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Get smallest sufficient team for voluntary work with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Get smallest sufficient team for voluntary work', + res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + res.locals.volunteer?.name || res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + userName: res.locals.volunteer?.name || res.locals.organizationAdmin?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Get smallest sufficient team for voluntary work with id: ' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Get smallest sufficient team for voluntary work', + res.locals.volunteer?.id || res.locals.organizationAdmin?.id, + res.locals.volunteer?.name || res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +router.put("/register/:id", validateVoluntaryWorkId, authorize("REGISTER_voluntaryWork"), async (req, res, next) => { + const voluntaryWork = await VoluntaryWork.findOne({ where: { id: Number(req.params.id) } }) + if (res.locals.volunteer) { + registerByVolunteer(Number(req.params.id), res.locals.volunteer?.volunteerProfile).then(async () => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: res.locals.volunteer?.type as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Register to voluntary work with id' + req.params.id + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Register to voluntary work with id' + req.params.id, + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + sendEmail( + res.locals.volunteer.email, + res.locals.volunteer.name, + 'Registration in Voluntary Work!', + `You have successfully registered in ${voluntaryWork?.name}!`) + + res.status(201).send("Registration done successfully!!") + }).catch(err => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: res.locals.volunteer?.type as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Register to voluntary work with id' + req.params.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Register to voluntary work with id' + req.params.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + next(err); + }); + } else if (res.locals.organizationAdmin) { + if (!req.body.volunteerId.toString()) { + res.status(400).send("volunteer id is required!"); + } + const volunteer = await Volunteer.findOne({ where: { id: (req.body.volunteerId.toString()) } }) + registerByOrganizationAdmin(Number(req.params.id), req.body.volunteerId.toString()).then(() => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Register By Organization Admin to voluntary work with id' + req.params.id + " volunteer id: " + req.body.volunteerId.toString() + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Register By Organization Admin to voluntary work with id' + req.params.id + " volunteer id: " + req.body.volunteerId.toString(), + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + if (volunteer) { + sendEmail( + volunteer.email, + volunteer.name, + 'Registration in Voluntary Work!', + `You have successfully registered in ${voluntaryWork?.name}!`) + } + + res.status(201).send("Registration done successfully!!") + }).catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Register By Organization Admin to voluntary work with id' + req.params.id + " volunteer id: " + req.body.volunteerId.toString() + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Register By Organization Admin to voluntary work with id' + req.params.id + " volunteer id: " + req.body.volunteerId.toString(), + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); + } +}); + +router.put("/deregister/:id", validateVoluntaryWorkId, authorize("DEREGISTER_voluntaryWork"), async (req, res, next) => { + const voluntaryWork = await VoluntaryWork.findOne({ where: { id: Number(req.params.id) } }) + const volunteer = await Volunteer.findOne({ where: { id: (req.body.volunteerId.toString()) } }) + + deregisterVoluntaryWork(Number(req.params.id), res.locals.volunteer.id || req.body.volunteerId.toString()).then(() => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Deregister to voluntary work with id' + req.params.id + " volunteer id: " + res.locals.volunteer?.id || req.body.volunteerId.toString() + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Deregister to voluntary work with id' + req.params.id + " volunteer id: " + res.locals.volunteer?.id || req.body.volunteerId.toString(), + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + sendEmail( + res.locals.volunteer.email || volunteer?.email, + res.locals.volunteer.name || volunteer?.name, + 'Deregistration from Voluntary Work!', + `You have unfortunately deregistered from ${voluntaryWork?.name}. We hope to see you in other voluntary works!`) + + res.status(201).send("Deregistration done successfully!!") + }).catch(err => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Deregister to voluntary work with id' + req.params.id + " volunteer id: " + res.locals.volunteer?.id || req.body.volunteerId.toString() + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Deregister to voluntary work with id' + req.params.id + " volunteer id: " + res.locals.volunteer?.id || req.body.volunteerId.toString(), + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + next(err); + }); +}); + +router.post("/generate-certificate/:id", validateVoluntaryWorkId, authorize("PUT_images"), async (req, res, next) => { + const currentDate = new Date(); + const date = `${currentDate.getDate()} ${currentDate.getMonth() + 1} ${currentDate.getFullYear()}` + + const payload = { page: "", pageSize: "", id: "", name: "", adminName: res.locals.organizationAdmin.name }; + const organization = await searchOrganizationProfile(payload); + const organizationName = organization?.name || ''; + + generateCertificate(Number(req.params.id), organizationName, req.body.date || date).then(() => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Certifications generated successfully for organization: ' + organizationName + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Certifications generated successfully for organization: ' + organizationName, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.status(201).send("Certifications generated and sent successfully!!") + + }).catch((err) => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Generating certifications for organization: ' + organizationName + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Generating certifications for organization: ' + organizationName, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }) + +}); + +router.put("/template/:id", validateVoluntaryWorkId, authorize("PUT_images"), async (req, res, next) => { + const templates = req.files?.template; + if (!templates) { + return res.status(400).send("No Template provided."); + } + + const uploadedFiles = Array.isArray(templates) ? templates : [templates]; + + const payload = { page: "", pageSize: "", id: "", name: "", adminName: res.locals.organizationAdmin.name }; + const organization = await searchOrganizationProfile(payload); + const organizationName = organization?.name || req.body.organizationName; + + await putCertificateTemplate(organizationName, uploadedFiles).then(() => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Template added successfully for organization: ' + organizationName + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Template added successfully for organization: ' + organizationName, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.status(201).send("Template added successfully!!") + + }).catch((err) => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Adding template for organization: ' + organizationName + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Adding template for organization: ' + organizationName, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }) + +}); + +router.delete('/certificate/:id', validateVoluntaryWorkId, authorize("DELETE_voluntaryWork"), validateDeleteFromS3, async (req, res, next) => { + const id = Number(req.params.id?.toString()); + const voluntaryWork = await getVoluntaryWork({ id }); + const organizationProfile = await searchOrganizationProfile({ page: "", pageSize: "", id: "", name: "", adminName: res.locals.organizationAdmin.name }); + const key = `certificates/${organizationProfile?.name || req.body.organizationName}/${voluntaryWork?.name}/${req.body.imageName}.pdf` + + deleteFromS3(key, "certificate") + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Delete certificate for volunteer: ' + req.body.volunteerName + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Delete certificate for volunteer: ' + req.body.volunteerName, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Delete image for volunteer: ' + req.body.volunteerName + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Delete image for volunteer: ' + req.body.volunteerName, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}) + +router.delete('/template/:id', validateOrganizationProfile, authorize("DELETE_voluntaryWork"), validateDeleteFromS3, async (req, res, next) => { + + const id = (req.params.id?.toString()); + const organizationProfile = await searchOrganizationProfile({ page: "", pageSize: "", id, name: "", adminName: '' }); + const key = `templates/${organizationProfile?.name}/${req.body.imageName || "certificate_template"}.html` + + deleteFromS3(key, "template") + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Delete template for organization :' + req.body.organizationName + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Delete template for organization :' + req.body.organizationName, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Delete template for organization :' + req.body.organizationName + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Delete template for organization :' + req.body.organizationName, + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}) + +router.get('/template/:id', authorize("PUT_images"), async (req, res, next) => { + const payload = { page: '', pageSize: '', id: '', name: '', adminName: res.locals.organizationAdmin.name } + const organizationProfile = await searchOrganizationProfile(payload); + + const prefix = `templates/${organizationProfile?.name || req.body.organizationName}` + loadFromS3(process.env.AWS_CERTIFICATES_BUCKET_NAME || '', prefix) + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Get template/s for organization: ' + req.body.organizationName + }).then().catch() + + logToCloudWatch( + 'success', + 'voluntary work', + 'Get template/s', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Get template/s for organization: ' + req.body.organizationName + }).then().catch() + + logToCloudWatch( + 'failed', + 'voluntary work', + 'Get template/s', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + next(err); + }); +}); + +export default router; + +/** + * @swagger + * tags: + * name: VoluntaryWork + * description: The voluntary work managing API + */ + +/** + * @swagger + * /voluntaryWork: + * post: + * summary: Create a new voluntary work entry + * tags: [VoluntaryWork] + * requestBody: + * description: Data for creating a new voluntary work entry + * required: true + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/VoluntaryWorkRequest' + * responses: + * 201: + * description: Voluntary work created successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/VoluntaryWorkResponse' + * 400: + * description: Bad Request, validation failed + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * components: + * schemas: + * VoluntaryWorkRequest: + * type: object + * properties: + * name: + * type: string + * description: + * type: string + * location: + * type: string + * time: + * type: array + * items: + * type: string + * example: ["Morning", "Afternoon"] + * status: + * type: string + * example: "Active" + * days: + * type: array + * items: + * type: string + * example: ["Monday", "Wednesday"] + * startedDate: + * type: string + * format: date + * finishedDate: + * type: string + * format: date + * capacity: + * type: integer + * skillTagIds: + * type: array + * items: + * type: integer + * example: + * name: "Voluntary Work Name" + * description: "Description of the voluntary work" + * location: "Voluntary Work Location" + * time: ["Morning", "Afternoon"] + * status: "Active" + * days: ["Monday", "Wednesday"] + * startedDate: "2023-10-26" + * finishedDate: "2023-10-28" + * capacity: 10 + * skillTagIds: [1, 2] + */ + +/** + * @swagger + * components: + * schemas: + * VoluntaryWorkRequest: + * type: object + * properties: + * name: + * type: string + * description: + * type: string + * location: + * type: string + * time: + * type: array + * items: + * type: string + * example: ["Morning", "Afternoon"] + * status: + * type: string + * example: "Active" + * days: + * type: array + * items: + * type: string + * example: ["Monday", "Wednesday"] + * startedDate: + * type: string + * format: date + * finishedDate: + * type: string + * format: date + * capacity: + * type: integer + * skillTagIds: + * type: array + * items: + * type: integer + * example: + * name: "Voluntary Work Name" + * description: "Description of the voluntary work" + * location: "Voluntary Work Location" + * time: ["Morning", "Afternoon"] + * status: "Active" + * days: ["Monday", "Wednesday"] + * startedDate: "2023-10-26" + * finishedDate: "2023-10-28" + * capacity: 10 + * skillTagIds: [1, 2] + + * VoluntaryWorkResponse: + * type: object + * properties: + * message: + * type: string + * data: + * type: object + * properties: + * id: + * type: string + * name: + * type: string + * startedDate: + * type: string + * format: date-time + * finishedDate: + * type: string + * format: date-time + * skillTagIds: + * type: array + * items: + * type: integer + * feedback: + * type: array + * items: + * type: object + * images: + * type: array + * items: + * type: string + * description: + * type: string + * days: + * type: array + * items: + * type: string + * time: + * type: array + * items: + * type: string + * location: + * type: string + * rating: + * type: number + * capacity: + * type: integer + * creatorId: + * type: string + * skillTags: + * type: array + * items: + * type: object + * volunteerProfiles: + * type: array + * items: + * type: object + * orgProfiles: + * type: object + * createdAt: + * type: string + * format: date-time + * example: + * message: "Voluntary work created successfully!!" + * data: + * id: "auto generated" + * name: "Voluntary Work Name" + * startedDate: "2023-10-26T00:00:00.000Z" + * finishedDate: "2023-10-28T00:00:00.000Z" + * skillTagIds: [1, 2] + * feedback: [] + * images: [] + * description: "Description of the voluntary work" + * days: ["Monday", "Wednesday"] + * location: "Voluntary Work Location" + * rating: 0 + * capacity: 10 + * creatorId: "Your Creator ID" + * skillTags: [] + + * time: ["Morning", "Afternoon"] + * createdAt: "2023-10-26T00:00:00.000Z" + */ + +/** + * @swagger + * /voluntaryWork/{id}: + * delete: + * summary: Delete a voluntary work entry by ID + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work entry to delete + * responses: + * 200: + * description: Voluntary work entry deleted successfully! + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 404: + * description: Voluntary work is not found. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/rating/{id}: + * post: + * summary: Send reminders to volunteers for rating and feedback + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work entry for which volunteers reminders should be sent + * responses: + * 201: + * description: Create remainder for rate and feedback successfully!! + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 404: + * description: Voluntary work is not found. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/image/{id}: + * delete: + * summary: Delete an image associated with a voluntary work entry + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work entry for which the image should be deleted + * requestBody: + * description: Data for deleting the image + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * organizationName: + * type: string + * description: The name of the organization (can be optional) + * imageName: + * type: string + * description: The name of the image to be deleted (without the file extension) + * required: + * - imageName + * example: + * organizationName: "Organization Name" + * imageName: "ImageName" + * responses: + * 200: + * description: Image deleted successfully ! + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 404: + * description: Voluntary work is not found + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/certificate/{id}: + * delete: + * summary: Delete a certificate associated with a voluntary work entry + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work entry for which the certificate should be deleted + * requestBody: + * description: Data for deleting the certificate + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * organizationName: + * type: string + * imageName: + * type: string + * volunteerName: + * type: string + * required: + * - imageName + * - volunteerName + * example: + * organizationName: "Organization Name" + * imageName: "CertificateName" + * volunteerName: "Volunteer Name" + * responses: + * 200: + * description: Certificate deleted successfully + * content: + * application/json: + * example: + * message: "Certificate deleted successfully" + * data: "Certificate deleted successfully!" + * 400: + * description: Bad Request. Validation failed. + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 404: + * description: Voluntary work is not found. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/template/{id}: + * delete: + * summary: Delete a template associated with an organization + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the organization to delete its template + * requestBody: + * description: Data for deleting the template + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * imageName: + * type: string + * required: + * - imageName + * example: + * imageName: "TemplateFileName" + * responses: + * 200: + * description: Template deleted successfully + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 404: + * description: Organization is not found + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/{id}: + * put: + * summary: Update a voluntary work entry by ID + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work entry to be updated + * requestBody: + * description: Data for updating the voluntary work entry + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * description: + * type: string + * location: + * type: string + * capacity: + * type: integer + * days: + * type: array + * items: + * type: string + * images: + * type: array + * items: + * type: string + * time: + * type: string + * status: + * type: string + * skillTagIds: + * type: array + * items: + * type: integer + * startedDate: + * type: string + * finishedDate: + * type: string + * required: + * false + * example: + * name: "Updated Voluntary Work Name" + * description: "Updated description for the voluntary work" + * location: "Updated location" + * capacity: 50 + * days: "Updated days" + * images: ["image1.jpg", "image2.jpg"] + * time: "Updated time" + * status: "Updated status" + * skillTagIds: [1, 2, 3] + * startedDate: "2023-10-31" + * finishedDate: "2023-11-30" + * responses: + * 201: + * description: Voluntary work updated successfully + * 400: + * description: Bad Request, validation failed + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 404: + * description: Organization is not found + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/search: + * get: + * summary: Search for voluntary work entries based on various filters + * tags: [VoluntaryWork] + * parameters: + * - in: query + * name: page + * description: Page number for pagination (default 1) + * schema: + * type: integer + * - in: query + * name: pageSize + * description: Number of entries per page (default 10) + * schema: + * type: integer + * - in: query + * name: id + * description: ID of the voluntary work entry + * schema: + * type: integer + * - in: query + * name: name + * description: Name of the voluntary work entry + * schema: + * type: string + * - in: query + * name: time + * description: Available time for the voluntary work entry + * schema: + * type: array + * items: + * type: string + * - in: query + * name: location + * description: Location of the voluntary work entry + * schema: + * type: string + * - in: query + * name: days + * description: Available days for the voluntary work entry + * schema: + * type: array + * items: + * type: string + * - in: query + * name: rating + * description: Minimum rating for the voluntary work entry + * schema: + * type: number + * - in: query + * name: status + * description: Status of the voluntary work entry + * schema: + * type: string + * - in: query + * name: skills + * description: Skill tags associated with the voluntary work entry + * schema: + * type: array + * items: + * type: string + * - in: query + * name: startedDate + * description: Voluntary work entry started date (e.g., "2023-10-31") + * schema: + * type: string + * - in: query + * name: finishedDate + * description: Voluntary work entry finished date (e.g., "2023-11-30") + * schema: + * type: string + * - in: query + * name: capacity + * description: Capacity of the voluntary work entry + * schema: + * type: integer + * - in: query + * name: ratingMore + * description: Filter for voluntary work entries with a rating greater than or equal to a specific value + * schema: + * type: number + * - in: query + * name: ratingLess + * description: Filter for voluntary work entries with a rating less than or equal to a specific value + * schema: + * type: number + * - in: query + * name: creatorId + * description: ID of the creator of the voluntary work entry + * schema: + * type: string + * responses: + * 200: + * description: Successful search for voluntary work entries + * content: + * application/json: + * schema: + * type: object + * properties: + * page: + * type: integer + * pageSize: + * type: integer + * total: + * type: integer + * voluntaryWorks: + * type: array + * items: + * type: object + * properties: + * name: + * type: string + * description: + * type: string + * days: + * type: string + * time: + * type: string + * location: + * type: string + * startedDate: + * type: string + * finishedDate: + * type: string + * status: + * type: string + * images: + * type: array + * items: + * type: string + * rating: + * type: number + * feedback: + * type: string + * capacity: + * type: integer + * skillTags: + * type: array + * items: + * type: object + * properties: + * name: + * type: string + * volunteers: + * type: array + * items: + * type: object + * properties: + * name: + * type: string + * volunteerNumbers: + * type: integer + * creatorId: + * type: string + * createdAt: + * type: string +* required: +* false + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/advanced-search: + * get: + * summary: Advanced search with a lot of details for voluntary work entries based on various filters + * tags: [VoluntaryWork] + * parameters: + * - in: query + * name: page + * description: Page number for pagination (default 1) + * schema: + * type: integer + * - in: query + * name: pageSize + * description: Number of entries per page (default 10) + * schema: + * type: integer + * - in: query + * name: id + * description: ID of the voluntary work entry + * schema: + * type: integer + * - in: query + * name: name + * description: Name of the voluntary work entry + * schema: + * type: string + * - in: query + * name: time + * description: Available time for the voluntary work entry + * schema: + * type: array + * items: + * type: string + * - in: query + * name: location + * description: Location of the voluntary work entry + * schema: + * type: string + * - in: query + * name: days + * description: Available days for the voluntary work entry + * schema: + * type: array + * items: + * type: string + * - in: query + * name: rating + * description: Minimum rating for the voluntary work entry + * schema: + * type: number + * - in: query + * name: status + * description: Status of the voluntary work entry + * schema: + * type: string + * - in: query + * name: skills + * description: Skill tags associated with the voluntary work entry + * schema: + * type: array + * items: + * type: string + * - in: query + * name: startedDate + * description: Voluntary work entry started date (e.g., "2023-10-31") + * schema: + * type: string + * - in: query + * name: finishedDate + * description: Voluntary work entry finished date (e.g., "2023-11-30") + * schema: + * type: string + * - in: query + * name: capacity + * description: Capacity of the voluntary work entry + * schema: + * type: integer + * - in: query + * name: finishedAfter + * description: Filter for voluntary work entries finished after a certain date + * schema: + * type: string + * - in: query + * name: finishedBefore + * description: Filter for voluntary work entries finished before a certain date + * schema: + * type: string + * - in: query + * name: startedAfter + * description: Filter for voluntary work entries started after a certain date + * schema: + * type: string + * - in: query + * name: startedBefore + * description: Filter for voluntary work entries started before a certain date + * schema: + * type: string + * - in: query + * name: ratingMore + * description: Filter for voluntary work entries with a rating greater than or equal to a specific value + * schema: + * type: number + * - in: query + * name: ratingLess + * description: Filter for voluntary work entries with a rating less than or equal to a specific value + * schema: + * type: number + * - in: query + * name: creatorId + * description: ID of the creator of the voluntary work entry + * schema: + * type: string + * responses: + * 200: + * description: Successful analysis and search for voluntary work entries + * content: + * application/json: + * schema: + * type: object + * properties: + * page: + * type: integer + * pageSize: + * type: integer + * total: + * type: integer + * voluntaryWorks: + * type: array + * items: + * type: object + * properties: + * name: + * type: string + * description: + * type: string + * days: + * type: string + * time: + * type: string + * location: + * type: string + * startedDate: + * type: string + * finishedDate: + * type: string + * status: + * type: string + * images: + * type: array + * items: + * type: string + * rating: + * type: number + * feedback: + * type: string + * capacity: + * type: integer + * skillTags: + * type: array + * items: + * type: object + * properties: + * name: + * type: string + * volunteers: + * type: array + * items: + * type: object + * properties: + * name: + * type: string + * volunteerNumbers: + * type: integer + * creatorId: + * type: string + * createdAt: + * type: string + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/recommendation: + * get: + * summary: Get voluntary work recommendations based on volunteer's information + * tags: [VoluntaryWork] + * parameters: + * - in: query + * name: page + * description: Page number for pagination (default 1) + * schema: + * type: integer + * - in: query + * name: pageSize + * description: Number of entries per page (default 10) + * schema: + * type: integer + * responses: + * 200: + * description: Successful retrieval of voluntary work recommendations + * content: + * application/json: + * schema: + * type: object + * properties: + * page: + * type: integer + * pageSize: + * type: integer + * total: + * type: integer + * voluntaryWorks: + * type: array + * items: + * type: object + * properties: + * name: + * type: string + * description: + * type: string + * days: + * type: string + * time: + * type: string + * location: + * type: string + * startedDate: + * type: string + * finishedDate: + * type: string + * status: + * type: string + * capacity: + * type: integer + * skillTags: + * type: array + * items: + * type: object + * properties: + * name: + * type: string + * volunteers: + * type: array + * items: + * type: object + * properties: + * name: + * type: string + * volunteerNumbers: + * type: integer + * createdAt: + * type: string + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/image/{id}: + * get: + * summary: Get images associated with a voluntary work entry + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work entry to retrieve images + * responses: + * 200: + * description: Successful retrieval of images + * content: + * application/json: + * schema: + * type: array + * items: + * type: string + * format: uri + * 401: + * description: Unauthorized. You do not have permission to access these images. + * 403: + * description: You don't have the permission + * 404: + * description: Voluntary work is not found. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/template/{id}: + * get: + * summary: Get templates associated with an organization + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the organization to retrieve its templates + * responses: + * 200: + * description: Successful retrieval of templates + * content: + * application/json: + * schema: + * type: array + * items: + * type: string + * format: uri + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 404: + * description: Organization not found. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/volunteer/{id}: + * get: + * summary: Get voluntary works associated with a volunteer + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: string + * required: true + * description: ID of the volunteer to retrieve their associated voluntary works + * responses: + * 200: + * description: Successful retrieval of voluntary works for the volunteer + * content: + * application/json: + * schema: + * type: array + * items: + * type: object + * properties: + * name: + * type: string + * description: + * type: string + * days: + * type: array + * items: + * type: string + * time: + * type: array + * items: + * type: string + * location: + * type: string + * startedDate: + * type: string + * finishedDate: + * type: string + * status: + * type: string + * capacity: + * type: integer + * skillTags: + * type: array + * items: + * type: string + * volunteers: + * type: array + * items: + * type: object + * properties: + * name: + * type: string + * volunteerNumbers: + * type: integer + * createdAt: + * type: string + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 404: + * description: Volunteer not found. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/rating/{id}: + * put: + * summary: Add or update the rating for a voluntary work + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work to add or update the rating + * requestBody: + * description: The rating to add or update for the voluntary work + * required: true + * content: + * application/json: + * schema: + * type: number + * example: + * rating: 4 + * responses: + * 201: + * description: Rating added or updated successfully + * 400: + * description: Bad Request, validation failed + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission. + * 404: + * description: Voluntary work not found. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/feedback/{id}: + * put: + * summary: Add feedback to a voluntary work + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work to add feedback + * requestBody: + * description: Feedback to add to the voluntary work + * required: true + * content: + * application/json: + * schema: + * type: string + * example: + * feedback: "This voluntary work was a great experience!" + * responses: + * 201: + * description: Feedback added successfully + * 400: + * description: Bad Request, validation failed + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 404: + * description: Voluntary work not found + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/image/{id}: + * put: + * summary: Add images to a voluntary work + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work to add images + * requestBody: + * required: true + * content: + * multipart/form-data: + * schema: + * type: object + * properties: + * image: + * type: array + * items: + * type: string + * example: + * image: [binary-data] + * responses: + * 201: + * description: Images added successfully + * 400: + * description: Bad Request, validation failed + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission. + * 404: + * description: Voluntary work not found. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/register/{id}: + * put: + * summary: Register in voluntary work + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work to register for + * requestBody: + * description: Registration request details + * required: false + * content: + * application/json: + * schema: + * type: object + * properties: + * volunteerId: + * type: string + * example: + * volunteerId: "12345" + * responses: + * 201: + * description: Registration completed successfully + * 400: + * description: Bad Request, validation failed + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission. + * 404: + * description: Voluntary work not found. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/deregister/{id}: + * put: + * summary: Deregister from a voluntary work + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work to deregister from + * requestBody: + * description: Deregistration request details + * required: false + * content: + * application/json: + * schema: + * type: object + * properties: + * volunteerId: + * type: string + * example: + * volunteerId: "12345" + * responses: + * 201: + * description: Deregistration completed successfully + * 400: + * description: Bad Request, validation failed + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission. + * 404: + * description: Voluntary work or volunteer not found. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/template/{id}: + * put: + * summary: Add a certificate template for an organization + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the organization for which to add a certificate template + * requestBody: + * description: Certificate template file to upload + * required: true + * content: + * multipart/form-data: + * schema: + * type: object + * properties: + * template: + * type: file + * example: + * template: certificate_template.html + * responses: + * 201: + * description: Certificate template added successfully + * 400: + * description: Bad Request, validation failed + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/generate-certificate/{id}: + * post: + * summary: Generate certificates for a voluntary work and send them to volunteers + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work for which to generate certificates + * requestBody: + * description: Request body to customize the certificates + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * date: + * type: string + * description: Date to include on the certificates + * example: + * date: "2023-10-12" + * responses: + * 201: + * description: Certificates generated and sent successfully + * 400: + * description: Bad Request, validation failed + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/rating-and-feedback/{id}: + * get: + * summary: Get ratings and feedback for a voluntary work + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work for which to get ratings and feedback + * responses: + * 200: + * description: Ratings and feedback retrieved successfully + * content: + * application/json: + * schema: + * type: object + * properties: + * avgRating: + * type: number + * description: Average rating for the voluntary work + * data: + * type: array + * items: + * type: object + * properties: + * volunteerName: + * type: string + * description: Name of the volunteer + * rating: + * type: number + * description: Rating given by the volunteer + * feedback: + * type: string + * description: Feedback provided by the volunteer + * example: + * avgRating: 4.5 + * data: + * - volunteerName: "John Doe" + * rating: 4 + * feedback: "Great experience!" + * - volunteerName: "Alice Smith" + * rating: 5 + * feedback: "Wonderful opportunity!" + * - volunteerName: "Eve Johnson" + * rating: 4 + * feedback: "Enjoyed the work but could be improved." + + * 404: + * description: Voluntary work not found. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/rating/{id}: + * delete: + * summary: Delete a rating for a voluntary work + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work from which to delete a rating + * responses: + * 200: + * description: Rating deleted successfully + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission. + * 404: + * description: Rating not found or Voluntary work not found. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/feedback/{id}: + * delete: + * summary: Delete feedback for a voluntary work + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: ID of the voluntary work from which to delete feedback + * responses: + * 200: + * description: Rating deleted successfully + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission. + * 404: + * description: Feedback not found or Voluntary work not found. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/analysis: + * get: + * summary: Get analysis of the voluntary work system + * tags: [VoluntaryWork] + * responses: + * 200: + * description: Analysis of the voluntary work system + * content: + * application/json: + * schema: + * type: object + * properties: + * avgRating: + * type: object + * description: Distribution of average ratings. + * example: + * '0-1': 10, + * '1-2': 20, + * '2-3': 30, + * '3-4': 40, + * '4-5': 50 + * status: + * type: object + * description: Distribution of voluntary work statuses. + * example: + * 'Pending': 5, + * 'In Progress': 10, + * 'Finished': 20, + * 'Canceled': 3 + * location: + * type: object + * description: Distribution of voluntary work locations. + * example: + * 'Location A': 15, + * 'Location B': 25, + * 'Location C': 10 + * capacity: + * type: object + * description: Distribution of voluntary work capacities. + * example: + * 20: 15, + * 30: 25, + * 40: 10 + * startedDates: + * type: object + * description: Distribution of when voluntary works were started. + * example: + * 'Last Week': 5, + * 'Last Month': 10, + * 'Last Year': 20 + * finishedDates: + * type: object + * description: Distribution of when voluntary works were finished. + * example: + * 'Last Week': 3, + * 'Last Month': 7, + * 'Last Year': 15 + * voluntaryWorkNumbers: + * type: integer + * description: Total number of voluntary works. + * example: 100 + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/analysis/{id}: + * get: + * summary: Get analysis of an organization's voluntary works + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * required: true + * description: Organization ID + * schema: + * type: string + * example: "12345" + * responses: + * 200: + * description: Analysis of the organization's voluntary works + * content: + * application/json: + * schema: + * type: object + * properties: + * voluntaryWorkNumbers: + * type: integer + * description: Total number of voluntary works within the organization. + * example: 100 + * avgRating: + * type: object + * description: Distribution of average ratings within the organization's voluntary works. + * example: + * '0-1': 10, + * '1-2': 20, + * '2-3': 30, + * '3-4': 40, + * '4-5': 50 + * status: + * type: object + * description: Distribution of voluntary work statuses within the organization. + * example: + * 'Pending': 5, + * 'In Progress': 10, + * 'Finished': 20, + * 'Canceled': 3 + * location: + * type: object + * description: Distribution of voluntary work locations within the organization. + * example: + * 'Location A': 15, + * 'Location B': 25, + * 'Location C': 10 + * capacity: + * type: object + * description: Distribution of voluntary work capacities within the organization. + * example: + * 20: 15, + * 30: 25, + * 40: 10 + * startedDates: + * type: object + * description: Distribution of when voluntary works were started within the organization. + * example: + * 'Last Week': 5, + * 'Last Month': 10, + * 'Last Year': 20 + * finishedDates: + * type: object + * description: Distribution of when voluntary works were finished within the organization. + * example: + * 'Last Week': 3, + * 'Last Month': 7, + * 'Last Year': 15 + * 401: + * description: You are unauthorized. + * 403: + * description: You don't have the permission. + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /voluntaryWork/sufficient-team/{id}: + * get: + * summary: Find the smallest sufficient team for a voluntary work + * tags: [VoluntaryWork] + * parameters: + * - in: path + * name: id + * required: true + * description: Voluntary work ID + * schema: + * type: integer + * example: 5 + * responses: + * 200: + * description: Smallest sufficient team for the voluntary work + * content: + * application/json: + * schema: + * type: object + * properties: + * smallestSufficientTeamNumber: + * type: integer + * description: Number of volunteers in the smallest sufficient team. + * example: 1 + * smallestSufficientTeam: + * type: array + * description: List of volunteers in the smallest sufficient team. + * items: + * type: object + * properties: + * id: + * type: integer + * description: Volunteer ID + * example: 123 + * name: + * type: string + * description: Volunteer's name + * example: John Doe + * email: + * type: string + * description: Volunteer's email + * example: john@example.com + * 401: + * description: You are unauthorized. + * 403: + * description: You don't have the permission. + * 404: + * description: Voluntary work not found. + * 500: + * description: Internal Server Error + */ + diff --git a/src/routes/volunteer.ts b/src/routes/volunteer.ts new file mode 100644 index 00000000..67013162 --- /dev/null +++ b/src/routes/volunteer.ts @@ -0,0 +1,921 @@ +import express from 'express'; +import { authorize, checkMe } from '../middleware/auth/authorize.js'; +import { authenticate } from '../middleware/auth/authenticate.js'; +import { validateEditedVolunteer, validateLogin, validateVolunteer, validateVolunteerId } from '../middleware/validation/volunteer.js'; +import { createVolunteer, deleteVolunteer, editVolunteer, forgetPassword, getVolunteers, login, resetPassword, verifyToken } from '../controllers/volunteer.js'; +import { NSVolunteer } from '../../types/volunteer.js'; +import { log } from '../controllers/dataBaseLogger.js'; +import { NSLogs } from '../../types/logs.js'; +import { logToCloudWatch } from '../controllers/AWSServices/CloudWatchLogs.js'; +import { sendEmail } from '../controllers/AWSServices/SES.js'; +import { Volunteer } from '../db/entities/Volunteer.js'; + +var router = express.Router(); + +router.post('/signup', validateVolunteer, (req, res, next) => { + createVolunteer({ ...req.body, type: "volunteer" }).then((data) => { + log({ + userId: data.id, + userName: req.body.name, + userType: data.type as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Signup volunteer ' + req.body.name + }).then().catch() + + logToCloudWatch( + 'success', + 'volunteer', + 'Signup volunteer ' + req.body.name, + data.id, + req.body.name + ).then().catch() + + sendEmail( + req.body.email, + req.body.name, + 'Signup volunteer in Serve And Shine', + 'You have successfully registered in Serve And Shine. You can now view voluntary organizations and works'); + + const { password, ...dataWithoutPassword } = data; + res.status(201).send({ message: "Volunteer created successfully!!", dataWithoutPassword }) + }).catch(async err => { + if (err.message.includes("Converting circular structure")) { + const data = await Volunteer.findOne({ where: { id: req.body.id } }); + if (data) { + + log({ + userId: data.id, + userName: req.body.name, + userType: data.type as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Signup volunteer ' + req.body.name + }).then().catch() + + logToCloudWatch( + 'success', + 'volunteer', + 'Signup volunteer ' + req.body.name, + data.id, + req.body.name + ).then().catch() + + sendEmail( + req.body.email, + req.body.name, + 'Signup volunteer in Serve And Shine', + 'You have successfully registered in Serve And Shine. You can now view voluntary organizations and works'); + + const { password, ...dataWithoutPassword } = data; + res.status(201).send({ message: "Volunteer created successfully!!", dataWithoutPassword }) + } + + } else { + log({ + userId: "", + userName: req.body.name, + userType: req.body.type as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Signup volunteer ' + req.body.name + }).then().catch() + + logToCloudWatch( + 'failed', + 'volunteer', + 'Signup volunteer ' + req.body.name, + "", + req.body.name + ).then().catch() + next(err); + } + }); +}); + +router.post('/login', validateLogin, (req, res, next) => { + const email = req.body.email; + const name = req.body.name; + const id = req.body.id; + login(email, name, id) + .then(data => { + res.cookie('myApp', data.token, { + httpOnly: true, + maxAge: 60 * 24 * 60 * 1000, + sameSite: "lax" // Protect against CSRF attacks + }); + + log({ + userId: id, + userName: name, + userType: (data.volunteer?.type) as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Login ' + (name) + }).then().catch() + + logToCloudWatch( + 'success', + 'volunteer', + 'Login ' + (name), + id, + name + ).then().catch() + + res.status(201).send("You logged in successfully !"); + }) + .catch(err => { + log({ + userId: id, + userName: name, + userType: 'volunteer' as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Login ' + (name) + }).then().catch() + + logToCloudWatch( + 'failed', + 'volunteer', + 'Login ' + name, + id, + name + ).then().catch() + + res.status(401).send(err); + }) +}); + +router.delete('/:id', authenticate, authorize("DELETE_volunteer"), validateVolunteerId, async (req, res, next) => { + const id = req.params.id?.toString(); + + deleteVolunteer(id) + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Delete Volunteer with id: ' + id + }).then().catch() + + logToCloudWatch( + 'success', + 'volunteer', + 'Delete Volunteer with id: ' + id, + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + res.send(data); + }) + .catch(error => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Delete Volunteer with id: ' + id + }).then().catch() + + logToCloudWatch( + 'failed', + 'volunteer', + 'Delete Volunteer with id: ' + id, + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + next(error); + }); +}) + +router.put("/:id", authenticate, authorize("PUT_volunteer"), validateEditedVolunteer, async (req, res, next) => { + editVolunteer({ ...req.body, id: req.params.id?.toString() }).then(() => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Edit Volunteer with id: ' + req.params.id?.toString() + }).then().catch() + + logToCloudWatch( + 'success', + 'volunteer', + 'Edit Volunteer with id: ' + req.params.id?.toString(), + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + res.status(201).send("Volunteer edited successfully!!") + }).catch(err => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Edit Volunteer with id: ' + req.params.id?.toString() + }).then().catch() + + logToCloudWatch( + 'failed', + 'volunteer', + 'Edit Volunteer with id: ' + req.params.id?.toString(), + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + next(err); + }); +}); + +router.get('/search', authenticate, authorize("GET_volunteers"), async (req, res, next) => { + const payload = { + page: req.query.page?.toString() || '1', + pageSize: req.query.pageSize?.toString() || '10', + id: req.query.id?.toString() || "", + name: req.query.name?.toString() || "", + email: req.query.email?.toString() || "", + availableLocation: req.query.availableLocation?.toString() || "", + skills: ((Array.isArray(req.query.skills) ? req.query.skills : [req.query.skills]).filter(Boolean)) as string[], + type: req.query.type as NSVolunteer.TypeVolunteer, + availableDays: (Array.isArray(req.query.availableDays) ? req.query.availableDays : [req.query.availableDays]).filter(Boolean) as NSVolunteer.AvailableDays[], + availableTime: ((Array.isArray(req.query.availableTime) ? req.query.availableTime : [req.query.availableTime]).filter(Boolean)) as NSVolunteer.AvailableTime[], + password: "" + }; + + getVolunteers(payload) + .then(data => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'get Volunteer/s' + }).then().catch() + + logToCloudWatch( + 'success', + 'volunteer', + 'get Volunteer/s', + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + res.send(data); + }) + .catch(err => { + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Get Volunteer/s' + }).then().catch() + + logToCloudWatch( + 'failed', + 'volunteer', + 'get Volunteer/s', + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + next(err); + }); +}); + +router.get("/logout", authenticate, (req, res, next) => { + res.cookie("name", '', { + maxAge: -1 + }) + res.cookie("myApp", '', { + maxAge: -1 + }) + log({ + userId: res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + userName: res.locals.organizationAdmin?.name || res.locals.volunteer?.name, + userType: (res.locals.volunteer ? res.locals.volunteer?.type : res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Logout ' + (res.locals.organizationAdmin?.name || res.locals.volunteer?.name) + }).then().catch() + + logToCloudWatch( + 'success', + 'volunteer', + 'Logout ' + (res.locals.organizationAdmin?.name || res.locals.volunteer?.name), + res.locals.organizationAdmin?.id || res.locals.volunteer?.id, + res.locals.organizationAdmin?.name || res.locals.volunteer?.name + ).then().catch() + + res.send("You logged out successfully !"); +}); + +router.get('/me', authenticate, async (req, res, next) => { + if (res.locals.volunteer) { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type) as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Get my information' + }).then().catch() + + logToCloudWatch( + 'success', + 'volunteer', + 'Get my information', + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + res.send(res.locals.volunteer); + } else if (res.locals.organizationAdmin) { + log({ + userId: res.locals.organizationAdmin?.id, + userName: res.locals.organizationAdmin?.name, + userType: (res.locals.organizationAdmin?.name === "root" ? "root" : 'admin') as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Get my information' + }).then().catch() + + logToCloudWatch( + 'failed', + 'organization admin', + 'Get my information', + res.locals.organizationAdmin?.id, + res.locals.organizationAdmin?.name + ).then().catch() + + res.send(res.locals.organizationAdmin); + } +}); + +router.get("/forget-password", authenticate, authorize("PUT_rating"), (req, res, next) => { + forgetPassword(res.locals.volunteer?.id, res.locals.volunteer?.email).then(() => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type) as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Forget password volunteer id ' + res.locals.volunteer?.id + }).then().catch() + + logToCloudWatch( + 'success', + 'volunteer', + 'Forget password volunteer id ' + res.locals.volunteer?.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + res.send("Password reset link has been sent to your email") + }).catch(err => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type) as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Forget password volunteer id ' + res.locals.volunteer?.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'volunteer', + 'Forget password volunteer id ' + res.locals.volunteer?.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + next(err); + }) +}) + +router.get("/reset-password/:id/:token", authenticate, authorize("PUT_rating"), validateVolunteerId, async (req, res, next) => { + const { id, token } = req.params; + + try { + await verifyToken(id, token); + res.cookie('reset-password', token, { + httpOnly: true, + maxAge: 15 * 60 * 1000, + sameSite: "lax" + }); + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type) as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Validate token to reset password for volunteer id ' + res.locals.volunteer?.id + }).then().catch() + + logToCloudWatch( + 'success', + 'volunteer', + 'Validate token to reset password for volunteer id ' + res.locals.volunteer?.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + res.send("You can now set your new password by making a POST request to /reset-password/:id with your new password in the request body."); + } catch (error) { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type) as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Validate token to reset password for volunteer id ' + res.locals.volunteer?.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'volunteer', + 'Validate token to reset password for volunteer id ' + res.locals.volunteer?.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + res.status(500).send("Invalid or expired token."); + } +}); + +router.post("/reset-password/:id", authenticate, authorize("PUT_rating"), validateVolunteerId, async (req, res, next) => { + const id = req.params.id; + const token = req.cookies['reset-password'] || ''; + const password = req.body.password; + // if(!password || !isValidPassword(password) )next() bad request + resetPassword(id, token, password).then(data => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type) as NSLogs.userType, + type: 'success' as NSLogs.Type, + request: 'Reset password for volunteer id ' + res.locals.volunteer?.id + }).then().catch() + + logToCloudWatch( + 'success', + 'volunteer', + 'Reset password for volunteer id ' + res.locals.volunteer?.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + res.status(200).send(data) + }).catch(err => { + log({ + userId: res.locals.volunteer?.id, + userName: res.locals.volunteer?.name, + userType: (res.locals.volunteer?.type) as NSLogs.userType, + type: 'failed' as NSLogs.Type, + request: 'Reset password for volunteer id ' + res.locals.volunteer?.id + }).then().catch() + + logToCloudWatch( + 'failed', + 'volunteer', + 'Reset password for volunteer id ' + res.locals.volunteer?.id, + res.locals.volunteer?.id, + res.locals.volunteer?.name + ).then().catch() + + // res.send(err) + }) +}); + +/** + * @swagger + * tags: + * name: Volunteer + * description: The Volunteer managing API + */ + + +/** + * @swagger + * /volunteer/login: + * post: + * summary: Login a volunteer + * tags: [Volunteer] + * requestBody: + * description: Volunteer data to sign up + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * email: + * type: string + * id: + * type: string + * example: + * name: "Volunteer 1" + * email: "volunteer1@gmail.com" + * id: "9635940b-6176-4148-8e62-7801233e9f85" + * responses: + * 200: + * description: Volunteer loged in successfully + * 401: + * description: You are unauthorized + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /volunteer/logout: + * get: + * summary: Logout a volunteer + * tags: [Volunteer] + * responses: + * 200: + * description: Volunteer loged out successfully + * 401: + * description: You are unauthorized + */ + +/** + * @swagger + * /volunteer/search: + * get: + * summary: Get volunteer based on the provided query parameters + * tags: [Volunteer] + * parameters: + * - in: query + * name: id + * schema: + * type: string + * description: Filter volunteer by ID + * - in: query + * name: name + * schema: + * type: string + * description: Filter volunteer by name + * - in: query + * name: email + * schema: + * type: string + * description: Filter volunteer by email + * - in: query + * name: availableLocation + * schema: + * type: string + * description: Filter volunteer by availableLocation + * - in: query + * name: availableTime + * schema: + * type: string + * description: Filter volunteer by availableTime + * - in: query + * name: availableDays + * schema: + * type: string + * description: Filter volunteer by availableDays + * responses: + * 200: + * description: Find volunteer + * content: + * application/json: + * schema: + * type: object + * properties: + * page: + * type: integer + * pageSize: + * type: integer + * total: + * type: integer + * volunteers: + * type: array + * items: + * type: object + * example: + * page: 1 + * pageSize: 10 + * total: 1 + * volunteers: + * - name: "Volunteer 1" + * email: "volunteer1@gamil.com" + * type: "volunteer" + * volunteerProfile: + * availableTime: ["Afternoon"] + * availableDays: ["Wednesday", "Saturday"] + * availableLocation: "main" + * dateOfBirth: null + * skillTags: ["softskills"] + * + * 404: + * description: Volunteer not found + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /volunteer/{id}: + * delete: + * summary: Delete a volunteer by ID + * tags: [Volunteer] + * parameters: + * - in: path + * name: id + * schema: + * type: string + * required: true + * description: ID of the volunteer to delete + * responses: + * 200: + * description: Volunteer deleted successfully + * 404: + * description: Volunteer not found + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /volunteer/me: + * get: + * summary: Get information about loged in volunteer + * tags: [Volunteer] + * responses: + * 200: + * description: Find me + * content: + * application/json: + * schema: + * type: object + * properties: + * volunteer: + * type: array + * items: + * type: object + * example: + * volunteer: + * - id: "1ff02f01-a8fd-4438-932b-df62b4a28dc2" + * name: "Volunteer 1" + * email: "volunteer1@gamil.com" + * password: "$2b$10$UodozOgAHz3HFr5tEwGcuuOuoGn/dJ8s07NBdQnyWMn8le5fMc.kO" + * type: "volunteer" + * createdAt: "2023-10-27T13:31:16.941Z" + * roles: + * id: 4 + * name: "volunteer" + * createdAt: "2023-10-25T21:42:11.784Z" + * permissions: + * - id: 1 + * name: "GET_me" + * createdAt: "2023-10-25T21:40:56.000Z" + * - id: 2 + * name: "GET_volunteers" + * createdAt: "2023-10-25T21:40:56.000Z" + * volunteerProfile: + * id: "c9e2bca2-5060-4c9e-bae7-60480e590d1" + * availableTime: ["Afternoon"] + * availableDays: ["Wednesday", "Saturday"] + * availableLocation: "main" + * dateOfBirth: null + * skillTags: + * id: 1 + * name: "softskills" + * createdAt: "2023-10-27T08:56:15.498Z" + * voluntaryWorks: [] + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /volunteer/signup: + * post: + * summary: Sign up a volunteer + * tags: [Volunteer] + * requestBody: + * description: Volunteer data to sign up + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * email: + * type: string + * password: + * type: string + * availableTime: + * type: array + * items: + * type: string + * availableDays: + * type: array + * items: + * type: string + * availableLocation: + * type: string + * skills: + * type: array + * items: + * type: string + * # Add other properties from NSVolunteer.Item as needed + * example: + * name: "Volunteer 1" + * email: "volunteer1@gmail.com" + * password: "volunteer123?" + * availableTime: ["Afternoon"] + * availableDays: ["Saturday", "Wednesday"] + * availableLocation: "main" + * skills: ["softskills"] + * responses: + * 201: + * description: Volunteer signed up successfully + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * data: + * # Define the structure of the returned data here + * example: + * message: "Volunteer signs up successfully" + * dataWithoutPassword: + * id: "7bd5f299-20b6-4aa5-87e4-fc416274f6b4" + * name: "Volunteer 1" + * email: "volunteer1@gmail.com" + * type: "volunteer" + * createdAt: "2023-10-27T08:56:15.827Z" + * 400: + * description: Bad request, validation failed + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /volunteer/{id}: + * put: + * summary: Edit a volunteer by ID + * tags: [Volunteer] + * parameters: + * - in: path + * name: id + * schema: + * type: string + * required: true + * description: ID of the volunteer to edit + * requestBody: + * description: Volunteer data to update + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * email: + * type: string + * newPassword: + * type: string + * oldPassword: + * type: string + * example: + * name: "New Name" + * + * responses: + * 200: + * description: Volunteer edited successfully + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: + * name: "Updated Volunteer Name" + * + * 404: + * description: Volunteer not found + * 401: + * description: You are unauthorized + * 403: + * description: You don't have the permission + * 500: + * description: Something went wrong + */ + +/** + * @swagger + * /volunteer/forget-password: + * get: + * summary: Send a password reset link to a volunteer's email + * tags: [Volunteer] + * security: + * - BearerAuth: [] + * responses: + * 200: + * description: Password reset link sent successfully + * content: + * text/plain: + * schema: + * type: string + * example: Password reset link has been sent to your email + * 401: + * description: Volunteer unauthorized + * 403: + * description: You don't have the permission. + * 500: + * description: Internal Server Error + */ + +/** + * @swagger + * /volunteer/reset-password/{id}/{token}: + * get: + * summary: Validate a password reset token for a volunteer + * tags: [Volunteer] + * parameters: + * - name: id + * in: path + * required: true + * description: The ID of the volunteer. + * schema: + * type: string + * - name: token + * in: path + * required: true + * description: The password reset token. + * schema: + * type: string + * responses: + * 200: + * description: Token validated successfully + * content: + * text/plain: + * schema: + * type: string + * example: You can now set your new password by making a POST request to /reset-password/{id} with your new password in the request body. + * 401: + * description: Volunteer unauthorized + * 403: + * description: You don't have the permission. + + * 500: + * description: Invalid or expired token. + */ + +/** + * @swagger + * /volunteer/reset-password/{id}: + * post: + * summary: Reset the password for a volunteer + * tags: [Volunteer] + * parameters: + * - name: id + * in: path + * required: true + * description: The ID of the volunteer. + * schema: + * type: string + + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * password: + * type: string + * responses: + * 200: + * description: Password updated successfully + * content: + * text/plain: + * schema: + * type: string + * example: Password updated successfully!! + * 401: + * description: Volunteer unauthorized + * 403: + * description: You don't have the permission. + * 400: + * description: Your request is BAD, + * 500: + * description: Internal Server Error + */ + +export default router; + diff --git a/src/utilities/AWSConfigureCloudWatch.ts b/src/utilities/AWSConfigureCloudWatch.ts new file mode 100644 index 00000000..120d969f --- /dev/null +++ b/src/utilities/AWSConfigureCloudWatch.ts @@ -0,0 +1,22 @@ +import AWS from 'aws-sdk'; + +const configureCloudWatch = () => { + const accessKeyId = process.env.AWS_ACCESS_KEY_ID; + const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; + + if (!accessKeyId || !secretAccessKey) { + throw 'AWS information to concent are missing :(' + } + + AWS.config.update({ + credentials: { + accessKeyId, + secretAccessKey, + }, + region: process.env.AWS_REGION, + }); + + return new AWS.CloudWatchLogs(); +} + +export { configureCloudWatch }; diff --git a/src/utilities/AWSConfigureLambdaFunction.ts b/src/utilities/AWSConfigureLambdaFunction.ts new file mode 100644 index 00000000..cd2003c1 --- /dev/null +++ b/src/utilities/AWSConfigureLambdaFunction.ts @@ -0,0 +1,22 @@ +import AWS from 'aws-sdk'; + +const configureLambda = async () => { + const accessKeyId = process.env.AWS_ACCESS_KEY_ID; + const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; + + if (!accessKeyId || !secretAccessKey) { + throw 'AWS information to concent are missing :(' + } + + AWS.config.update({ + credentials: { + accessKeyId, + secretAccessKey, + }, + region: process.env.AWS_REGION, + }); + + return new AWS.Lambda(); +} + +export { configureLambda }; \ No newline at end of file diff --git a/src/utilities/AWSConfigureS3.ts b/src/utilities/AWSConfigureS3.ts new file mode 100644 index 00000000..ffc1c958 --- /dev/null +++ b/src/utilities/AWSConfigureS3.ts @@ -0,0 +1,22 @@ +import AWS from 'aws-sdk'; + +const configureS3Bucket = async () => { + const accessKeyId = process.env.AWS_ACCESS_KEY_ID; + const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; + + if (!accessKeyId || !secretAccessKey) { + throw 'AWS information to concent are missing :(' + } + + AWS.config.update({ + credentials: { + accessKeyId, + secretAccessKey, + }, + region: process.env.AWS_REGION, + }); + + return new AWS.S3(); +} + +export { configureS3Bucket }; \ No newline at end of file diff --git a/src/utilities/AWSConfigureSES.ts b/src/utilities/AWSConfigureSES.ts new file mode 100644 index 00000000..13b0e100 --- /dev/null +++ b/src/utilities/AWSConfigureSES.ts @@ -0,0 +1,22 @@ +import AWS from 'aws-sdk'; + +const configureSES = async () => { + const accessKeyId = process.env.AWS_ACCESS_KEY_ID; + const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; + + if (!accessKeyId || !secretAccessKey) { + throw 'AWS information to concent are missing :(' + } + + AWS.config.update({ + credentials: { + accessKeyId, + secretAccessKey, + }, + region: process.env.AWS_REGION, + }); + + return new AWS.SES(); +} + +export { configureSES }; \ No newline at end of file diff --git a/swaggerConfig.ts b/swaggerConfig.ts new file mode 100644 index 00000000..ded3d6c1 --- /dev/null +++ b/swaggerConfig.ts @@ -0,0 +1,21 @@ + +import swaggerJsdoc from 'swagger-jsdoc'; + +const options = { + definition: { + openapi: "3.0.0", + info: { + title:"Serve-and-Shine", + version: "1.0.0" + }, + servers: [{ + url:"http://localhost:3000" + }], + + }, + apis: ["./dist/src/routes/*.js"] +}; + +const swaggerSpec = swaggerJsdoc(options); + +export { swaggerSpec }; diff --git a/types/error.ts b/types/error.ts new file mode 100644 index 00000000..5d683a45 --- /dev/null +++ b/types/error.ts @@ -0,0 +1,7 @@ +export namespace NSError { + + export interface Item { + status: number; + message: string; + } +} diff --git a/types/logs.ts b/types/logs.ts new file mode 100644 index 00000000..5d16c565 --- /dev/null +++ b/types/logs.ts @@ -0,0 +1,24 @@ +export namespace NSLogs { + + export enum userType { + root = 'root', + admin = 'admin', + volunteer = 'volunteer', + premium = 'premium' + } + + export enum Type { + success = 'success', + failed = 'failed' + } + + export interface Item { + id?: number; + userId: string; + userName: string; + userType: userType; + type:Type; + request: string; + createdAt?: Date; + } +} diff --git a/types/organizationAdmin.ts b/types/organizationAdmin.ts new file mode 100644 index 00000000..08642d2a --- /dev/null +++ b/types/organizationAdmin.ts @@ -0,0 +1,13 @@ +import { NSVolunteer } from "./volunteer.js"; + +export namespace NSOrganizationAdmin { + + export interface Item { + id?: string; + name: string; + email: string; + password: string; + organizationId: string; + createdAt?: Date; + } +} diff --git a/types/organizationProfile.ts b/types/organizationProfile.ts new file mode 100644 index 00000000..e53bd549 --- /dev/null +++ b/types/organizationProfile.ts @@ -0,0 +1,9 @@ +export namespace NSOrganizationProfile { + + export interface Item { + id?: string; + name: string; + description: string; + createdAt?: Date; + } +} diff --git a/types/permission.ts b/types/permission.ts new file mode 100644 index 00000000..f5650dbc --- /dev/null +++ b/types/permission.ts @@ -0,0 +1,9 @@ +export namespace NSPermission { + + export interface Item { + id?: number, + name: string, + rolesIds?: number[], + createdAt?: Date + } +} \ No newline at end of file diff --git a/types/role.ts b/types/role.ts new file mode 100644 index 00000000..a0dfb166 --- /dev/null +++ b/types/role.ts @@ -0,0 +1,17 @@ +export namespace NSRole { + export enum Type { + root = 'root', + admin = 'admin', + volunteer = 'volunteer', + premium = 'premium' + } + + export interface Item { + id?: number, + name: Type, + createdAt?: Date, + permissionsId: number[], + volunteerId?: string[], + organizationAdmin?: string[] + } +} \ No newline at end of file diff --git a/types/skillTag.ts b/types/skillTag.ts new file mode 100644 index 00000000..54b26c09 --- /dev/null +++ b/types/skillTag.ts @@ -0,0 +1,8 @@ +export namespace NSSkillTag { + + export interface Item { + id?: string; + name: string; + createdAt?: Date; + } +} diff --git a/types/voluntaryWork.ts b/types/voluntaryWork.ts new file mode 100644 index 00000000..5a7a9349 --- /dev/null +++ b/types/voluntaryWork.ts @@ -0,0 +1,104 @@ +import { SkillTag } from "../src/db/entities/SkillTag.js"; +import { NSVolunteer } from "./volunteer.js"; + +export namespace NSVoluntaryWork { + + export enum StatusType { + Pending = 'Pending', + InProgress = 'In Progress', + Finished = 'Finished', + Canceled = 'Canceled' + } + + export interface Edit { + id: string; + name?: string; + description?: string; + location?: string; + time?: NSVolunteer.AvailableTime[]; + images?: string[]; + avgRating?: number; + feedback?: NSVoluntaryWork.Feedback[]; + rating: NSVoluntaryWork.Rating[]; + status?: StatusType; + days?: NSVolunteer.AvailableDays[]; + startedDate?: string; + finishedDate?: string; + capacity?: number; + skillTagIds?: number[]; + isSkillsRequired?: boolean; + createdAt?: Date; + + } + + export interface GetVoluntaryWorks { + page: string, + pageSize: string, + id: number, + name: string, + time: NSVolunteer.AvailableTime[], + location: string, + days: NSVolunteer.AvailableDays[], + avgRating: number, + status: NSVoluntaryWork.StatusType, + skills: string[], + startedDate: string; + finishedDate: string; + capacity: number; + finishedAfter: string; + finishedBefore: string; + startedAfter: string; + startedBefore: string; + avgRatingMore: number; + avgRatingLess: number; + isSkillsRequired: boolean; + creatorId: string; + } + + export interface Date { + year: number; + month: number; + day: number; + }; + + export interface Item { + id?: string; + name: string; + description: string; + location: string; + time: NSVolunteer.AvailableTime[]; + images?: string[]; + avgRating?: number; + feedback?: NSVoluntaryWork.Feedback[]; + rating: NSVoluntaryWork.Rating[]; + status: StatusType; + createdAt?: Date; + days: NSVolunteer.AvailableDays[]; + startedDate: string; + finishedDate: string; + capacity: number; + skillTagIds: number[]; + isSkillsRequired: boolean; + creatorId: string; + } + + export interface Recommendation { + page: string, + pageSize: string, + time: NSVolunteer.AvailableTime[], + location: string, + days: NSVolunteer.AvailableDays[], + status: NSVoluntaryWork.StatusType, + skillTags: number[] + } + + export interface Rating { + volunteerName: string, + rating: number + } + + export interface Feedback { + volunteerName: string, + feedback: string + } +} diff --git a/types/volunteer.ts b/types/volunteer.ts new file mode 100644 index 00000000..9287deec --- /dev/null +++ b/types/volunteer.ts @@ -0,0 +1,55 @@ +import { VolunteerProfile } from "../src/db/entities/VolunteerProfile.js"; +import { Role } from "../src/db/entities/Role.js"; + + +export namespace NSVolunteer { + + export enum AvailableDays { + Sunday = 'Sunday', + Monday = 'Monday', + Tuesday = 'Tuesday', + Wednesday = 'Wednesday', + Thursday = 'Thursday', + Friday = 'Friday', + Saturday = 'Saturday', + } + + export enum Gender { + male = 'male', + female = "female" + } + + export enum AvailableTime { + Morning = 'Morning', + Afternoon = 'Afternoon' + } + + export enum TypeVolunteer { + volunteer = "volunteer", + premium = "premium" + } + + export interface Item { + id?: string; + name: string; + email: string; + password: string; + createdAt?: Date; + type?: TypeVolunteer; + availableTime: AvailableTime[]; + availableLocation: string; + availableDays: AvailableDays[]; + skills: string[]; + } + + export interface IVolunteer { + volunteerProfile: VolunteerProfile; + id: string; + name: string; + email: string; + password: string; + type: 'volunteer' | 'premium'; + roles: Role[]; + createdAt: Date; + } +} \ No newline at end of file